NestedFolders: Basic search view (#67093)

* First stab and reusing SearchView for new Browse Dashboards

* NestedFolders: Basic SearchView

* last bits of cleanup
This commit is contained in:
Josh Hunt
2023-04-24 16:32:04 +01:00
committed by GitHub
parent 2fb1c64e80
commit 69e5a2bdf9
4 changed files with 90 additions and 13 deletions

View File

@@ -50,7 +50,7 @@ const BrowseDashboardsPage = memo(({ match, location }: Props) => {
<AutoSizer>
{({ width, height }) =>
searchState.query ? (
<SearchView searchState={searchState} />
<SearchView width={width} height={height} folderUID={folderUID} />
) : (
<BrowseView width={width} height={height} folderUID={folderUID} />
)

View File

@@ -1,17 +1,91 @@
import React from 'react';
import React, { useCallback, useEffect } from 'react';
import { parseRouteParams } from 'app/features/search/utils';
import { Spinner } from '@grafana/ui';
import { useKeyNavigationListener } from 'app/features/search/hooks/useSearchKeyboardSelection';
import { SearchResultsProps, SearchResultsTable } from 'app/features/search/page/components/SearchResultsTable';
import { getSearchStateManager } from 'app/features/search/state/SearchStateManager';
import { DashboardViewItemKind } from 'app/features/search/types';
import { useDispatch, useSelector } from 'app/types';
import { setItemSelectionState } from '../state';
interface SearchViewProps {
searchState: ReturnType<typeof parseRouteParams>;
height: number;
width: number;
folderUID: string | undefined;
}
export function SearchView({ searchState }: SearchViewProps) {
return (
<div>
<p>SearchView</p>
export function SearchView({ folderUID, width, height }: SearchViewProps) {
const dispatch = useDispatch();
const selectedItems = useSelector((wholeState) => wholeState.browseDashboards.selectedItems);
<pre>{JSON.stringify(searchState, null, 2)}</pre>
</div>
const { keyboardEvents } = useKeyNavigationListener();
const stateManager = getSearchStateManager();
useEffect(() => stateManager.initStateFromUrl(folderUID), [folderUID, stateManager]);
const state = stateManager.useState();
const value = state.result;
const selectionChecker = useCallback(
(kind: string | undefined, uid: string): boolean => {
if (!kind || kind === '*') {
return false;
}
return selectedItems[assertDashboardViewItemKind(kind)][uid] ?? false;
},
[selectedItems]
);
const clearSelection = useCallback(() => {
console.log('TODO: clearSelection');
}, []);
const handleItemSelectionChange = useCallback(
(kind: string, uid: string) => {
const newIsSelected = !selectionChecker(kind, uid);
dispatch(
setItemSelectionState({ item: { kind: assertDashboardViewItemKind(kind), uid }, isSelected: newIsSelected })
);
},
[selectionChecker, dispatch]
);
if (!value) {
return (
<div>
<Spinner />
</div>
);
}
const props: SearchResultsProps = {
response: value,
selection: selectionChecker,
selectionToggle: handleItemSelectionChange,
clearSelection,
width: width,
height: height,
onTagSelected: stateManager.onAddTag,
keyboardEvents,
onDatasourceChange: state.datasource ? stateManager.onDatasourceChange : undefined,
onClickItem: stateManager.onSearchItemClicked,
};
return <SearchResultsTable {...props} />;
}
function assertDashboardViewItemKind(kind: string): DashboardViewItemKind {
switch (kind) {
case 'folder':
return 'folder';
case 'dashboard':
return 'dashboard';
case 'panel':
return 'panel';
}
throw new Error('Unsupported kind' + kind);
}

View File

@@ -38,7 +38,10 @@ export function setFolderOpenState(
export function setItemSelectionState(
state: BrowseDashboardsState,
action: PayloadAction<{ item: DashboardViewItem; isSelected: boolean }>
// SearchView doesn't use DashboardViewItemKind (yet), so we pick just the specific properties
// we're interested in
action: PayloadAction<{ item: Pick<DashboardViewItem, 'kind' | 'uid' | 'parentUID'>; isSelected: boolean }>
) {
const { item, isSelected } = action.payload;

View File

@@ -1,5 +1,7 @@
import { DashboardViewItem as DashboardViewItem, DashboardViewItemKind } from 'app/features/search/types';
export type DashboardTreeSelection = Record<DashboardViewItemKind, Record<string, boolean | undefined>>;
export interface BrowseDashboardsState {
rootItems: DashboardViewItem[];
childrenByParentUID: Record<string, DashboardViewItem[] | undefined>;
@@ -22,6 +24,4 @@ export interface DashboardsTreeItem<T extends DashboardViewItemWithUIItems = Das
isOpen: boolean;
}
export type DashboardTreeSelection = Record<DashboardViewItemKind, Record<string, boolean | undefined>>;
export const INDENT_AMOUNT_CSS_VAR = '--dashboards-tree-indentation';