mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
@@ -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} />
|
||||
)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user