mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
134 lines
4.3 KiB
TypeScript
134 lines
4.3 KiB
TypeScript
import React, { useCallback } from 'react';
|
|
|
|
import { DataFrameView, toDataFrame } from '@grafana/data';
|
|
import { Button, EmptyState } from '@grafana/ui';
|
|
import { Trans, t } from 'app/core/internationalization';
|
|
import { useKeyNavigationListener } from 'app/features/search/hooks/useSearchKeyboardSelection';
|
|
import { SearchResultsProps, SearchResultsTable } from 'app/features/search/page/components/SearchResultsTable';
|
|
import { useSearchStateManager } from 'app/features/search/state/SearchStateManager';
|
|
import { DashboardViewItemKind } from 'app/features/search/types';
|
|
import { useDispatch, useSelector } from 'app/types';
|
|
|
|
import { setAllSelection, setItemSelectionState, useHasSelection } from '../state';
|
|
|
|
interface SearchViewProps {
|
|
height: number;
|
|
width: number;
|
|
canSelect: boolean;
|
|
}
|
|
|
|
const NUM_PLACEHOLDER_ROWS = 50;
|
|
const initialLoadingView = {
|
|
view: new DataFrameView(
|
|
toDataFrame({
|
|
fields: [
|
|
{ name: 'uid', display: true, values: Array(NUM_PLACEHOLDER_ROWS).fill(null) },
|
|
{ name: 'kind', display: true, values: Array(NUM_PLACEHOLDER_ROWS).fill('dashboard') },
|
|
{ name: 'name', display: true, values: Array(NUM_PLACEHOLDER_ROWS).fill('') },
|
|
{ name: 'location', display: true, values: Array(NUM_PLACEHOLDER_ROWS).fill('') },
|
|
{ name: 'tags', display: true, values: Array(NUM_PLACEHOLDER_ROWS).fill([]) },
|
|
],
|
|
meta: {
|
|
custom: {
|
|
locationInfo: [],
|
|
},
|
|
},
|
|
})
|
|
),
|
|
loadMoreItems: () => Promise.resolve(),
|
|
// this is key and controls whether to show the skeleton in generateColumns
|
|
isItemLoaded: () => false,
|
|
totalRows: NUM_PLACEHOLDER_ROWS,
|
|
};
|
|
|
|
export function SearchView({ width, height, canSelect }: SearchViewProps) {
|
|
const dispatch = useDispatch();
|
|
const selectedItems = useSelector((wholeState) => wholeState.browseDashboards.selectedItems);
|
|
const hasSelection = useHasSelection();
|
|
|
|
const { keyboardEvents } = useKeyNavigationListener();
|
|
const [searchState, stateManager] = useSearchStateManager();
|
|
|
|
const value = searchState.result ?? initialLoadingView;
|
|
|
|
const selectionChecker = useCallback(
|
|
(kind: string | undefined, uid: string): boolean => {
|
|
if (!kind) {
|
|
return false;
|
|
}
|
|
|
|
// Currently, this indicates _some_ items are selected, not nessicarily all are
|
|
// selected.
|
|
if (kind === '*' && uid === '*') {
|
|
return hasSelection;
|
|
} else if (kind === '*') {
|
|
// Unsure how this case can happen
|
|
return false;
|
|
}
|
|
|
|
return selectedItems[assertDashboardViewItemKind(kind)][uid] ?? false;
|
|
},
|
|
[selectedItems, hasSelection]
|
|
);
|
|
|
|
const clearSelection = useCallback(() => {
|
|
dispatch(setAllSelection({ isSelected: false, folderUID: undefined }));
|
|
}, [dispatch]);
|
|
|
|
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.totalRows === 0) {
|
|
return (
|
|
<div style={{ width }}>
|
|
<EmptyState
|
|
button={
|
|
<Button variant="secondary" onClick={stateManager.onClearSearchAndFilters}>
|
|
<Trans i18nKey="browse-dashboards.no-results.clear">Clear search and filters</Trans>
|
|
</Button>
|
|
}
|
|
message={t('browse-dashboards.no-results.text', 'No results found for your query')}
|
|
variant="not-found"
|
|
role="alert"
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const props: SearchResultsProps = {
|
|
response: value,
|
|
selection: canSelect ? selectionChecker : undefined,
|
|
selectionToggle: canSelect ? handleItemSelectionChange : undefined,
|
|
clearSelection,
|
|
width: width,
|
|
height: height,
|
|
onTagSelected: stateManager.onAddTag,
|
|
keyboardEvents,
|
|
onDatasourceChange: searchState.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);
|
|
}
|