D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
usr
/
share
/
grafana
/
public
/
app
/
features
/
search
/
page
/
components
/
Filename :
SearchResultsCards.tsx
back
Copy
/* eslint-disable react/jsx-no-undef */ import { css } from '@emotion/css'; import React, { useEffect, useRef, useCallback, useState, CSSProperties } from 'react'; import { FixedSizeList } from 'react-window'; import InfiniteLoader from 'react-window-infinite-loader'; import { GrafanaTheme2 } from '@grafana/data'; import { useStyles2 } from '@grafana/ui'; import { SearchItem } from '../../components/SearchItem'; import { useSearchKeyboardNavigation } from '../../hooks/useSearchKeyboardSelection'; import { queryResultToViewItem } from '../../service/utils'; import { SearchResultsProps } from './SearchResultsTable'; export const SearchResultsCards = React.memo( ({ response, width, height, selection, selectionToggle, onTagSelected, keyboardEvents, onClickItem, }: SearchResultsProps) => { const styles = useStyles2(getStyles); const infiniteLoaderRef = useRef<InfiniteLoader>(null); const [listEl, setListEl] = useState<FixedSizeList | null>(null); const highlightIndex = useSearchKeyboardNavigation(keyboardEvents, 0, response); // Scroll to the top and clear loader cache when the query results change useEffect(() => { if (infiniteLoaderRef.current) { infiniteLoaderRef.current.resetloadMoreItemsCache(); } if (listEl) { listEl.scrollTo(0); } }, [response, listEl]); const RenderRow = useCallback( ({ index: rowIndex, style }: { index: number; style: CSSProperties }) => { let className = ''; if (rowIndex === highlightIndex.y) { className += ' ' + styles.selectedRow; } const item = response.view.get(rowIndex); const searchItem = queryResultToViewItem(item, response.view); const isSelected = selectionToggle && selection?.(searchItem.kind, searchItem.uid); return ( <div style={style} key={item.uid} className={className} role="row"> <SearchItem item={searchItem} onTagSelected={onTagSelected} onToggleChecked={(item) => { if (selectionToggle) { selectionToggle('dashboard', item.uid!); } }} editable={Boolean(selection != null)} onClickItem={onClickItem} isSelected={isSelected} /> </div> ); }, [response.view, highlightIndex, styles, onTagSelected, selection, selectionToggle, onClickItem] ); if (!response.totalRows) { return ( <div className={styles.noData} style={{ width }}> No data </div> ); } return ( <div aria-label="Search results list" style={{ width }} role="list"> <InfiniteLoader ref={infiniteLoaderRef} isItemLoaded={response.isItemLoaded} itemCount={response.totalRows} loadMoreItems={response.loadMoreItems} > {({ onItemsRendered, ref }) => ( <FixedSizeList ref={(innerRef) => { ref(innerRef); setListEl(innerRef); }} onItemsRendered={onItemsRendered} height={height} itemCount={response.totalRows} itemSize={72} width="100%" style={{ overflow: 'hidden auto' }} > {RenderRow} </FixedSizeList> )} </InfiniteLoader> </div> ); } ); SearchResultsCards.displayName = 'SearchResultsCards'; const getStyles = (theme: GrafanaTheme2) => { return { noData: css` display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; `, selectedRow: css` border-left: 3px solid ${theme.colors.primary.border}; `, }; };