Submit
Path:
~
/
/
usr
/
share
/
grafana
/
public
/
app
/
features
/
library-panels
/
components
/
LibraryPanelsSearch
/
File Content:
LibraryPanelsSearch.tsx
import { css } from '@emotion/css'; import React, { useCallback, useState } from 'react'; import { useDebounce } from 'react-use'; import { GrafanaTheme2, PanelPluginMeta, SelectableValue } from '@grafana/data'; import { useStyles2, VerticalGroup, FilterInput } from '@grafana/ui'; import { FolderInfo } from 'app/types'; import { FolderFilter } from '../../../../core/components/FolderFilter/FolderFilter'; import { PanelTypeFilter } from '../../../../core/components/PanelTypeFilter/PanelTypeFilter'; import { SortPicker } from '../../../../core/components/Select/SortPicker'; import { DEFAULT_PER_PAGE_PAGINATION } from '../../../../core/constants'; import { LibraryElementDTO } from '../../types'; import { LibraryPanelsView } from '../LibraryPanelsView/LibraryPanelsView'; export enum LibraryPanelsSearchVariant { Tight = 'tight', Spacious = 'spacious', } export interface LibraryPanelsSearchProps { onClick: (panel: LibraryElementDTO) => void; variant?: LibraryPanelsSearchVariant; showSort?: boolean; showPanelFilter?: boolean; showFolderFilter?: boolean; showSecondaryActions?: boolean; currentPanelId?: string; currentFolderUID?: string; perPage?: number; } export const LibraryPanelsSearch = ({ onClick, variant = LibraryPanelsSearchVariant.Spacious, currentPanelId, currentFolderUID, perPage = DEFAULT_PER_PAGE_PAGINATION, showPanelFilter = false, showFolderFilter = false, showSort = false, showSecondaryActions = false, }: LibraryPanelsSearchProps): JSX.Element => { const styles = useStyles2(getStyles, variant); const [searchQuery, setSearchQuery] = useState(''); const [debouncedSearchQuery, setDebouncedSearchQuery] = useState(''); useDebounce(() => setDebouncedSearchQuery(searchQuery), 200, [searchQuery]); const [sortDirection, setSortDirection] = useState<SelectableValue<string>>({}); const [folderFilter, setFolderFilter] = useState<string[]>(currentFolderUID ? [currentFolderUID] : []); const [panelFilter, setPanelFilter] = useState<string[]>([]); const sortOrFiltersVisible = showSort || showPanelFilter || showFolderFilter; const verticalGroupSpacing = variant === LibraryPanelsSearchVariant.Tight ? 'lg' : 'xs'; return ( <div className={styles.container}> <VerticalGroup spacing={verticalGroupSpacing}> <div className={styles.gridContainer}> <div className={styles.filterInputWrapper}> <FilterInput value={searchQuery} onChange={setSearchQuery} placeholder="Search by name or description" width={0} escapeRegex={false} /> </div> {sortOrFiltersVisible && ( <SearchControls showSort={showSort} showPanelFilter={showPanelFilter} showFolderFilter={showFolderFilter} onSortChange={setSortDirection} onFolderFilterChange={setFolderFilter} onPanelFilterChange={setPanelFilter} sortDirection={sortDirection.value} variant={variant} /> )} </div> <div className={styles.libraryPanelsView}> <LibraryPanelsView onClickCard={onClick} searchString={debouncedSearchQuery} sortDirection={sortDirection.value} panelFilter={panelFilter} folderFilter={folderFilter} currentPanelId={currentPanelId} showSecondaryActions={showSecondaryActions} perPage={perPage} /> </div> </VerticalGroup> </div> ); }; function getStyles(theme: GrafanaTheme2, variant: LibraryPanelsSearchVariant) { const tightLayout = css` flex-direction: row; row-gap: ${theme.spacing(1)}; `; return { filterInputWrapper: css` flex-grow: ${variant === LibraryPanelsSearchVariant.Tight ? 1 : 'initial'}; `, container: css` width: 100%; overflow-y: auto; padding: ${theme.spacing(1)}; `, libraryPanelsView: css` width: 100%; `, gridContainer: css` ${variant === LibraryPanelsSearchVariant.Tight ? tightLayout : ''}; display: flex; flex-direction: column; width: 100%; column-gap: ${theme.spacing(1)}; row-gap: ${theme.spacing(1)}; padding-bottom: ${theme.spacing(2)}; `, }; } interface SearchControlsProps { showSort: boolean; showPanelFilter: boolean; showFolderFilter: boolean; sortDirection?: string; onSortChange: (sortValue: SelectableValue) => void; onFolderFilterChange: (folder: string[]) => void; onPanelFilterChange: (plugins: string[]) => void; variant?: LibraryPanelsSearchVariant; } const SearchControls = React.memo( ({ variant = LibraryPanelsSearchVariant.Spacious, showSort, showPanelFilter, showFolderFilter, sortDirection, onSortChange, onFolderFilterChange, onPanelFilterChange, }: SearchControlsProps) => { const styles = useStyles2(getRowStyles, variant); const panelFilterChanged = useCallback( (plugins: PanelPluginMeta[]) => onPanelFilterChange(plugins.map((p) => p.id)), [onPanelFilterChange] ); const folderFilterChanged = useCallback( (folders: FolderInfo[]) => onFolderFilterChange(folders.map((f) => f.uid ?? '')), [onFolderFilterChange] ); return ( <div className={styles.container}> {showSort && <SortPicker value={sortDirection} onChange={onSortChange} filter={['alpha-asc', 'alpha-desc']} />} {(showFolderFilter || showPanelFilter) && ( <div className={styles.filterContainer}> {showFolderFilter && <FolderFilter onChange={folderFilterChanged} />} {showPanelFilter && <PanelTypeFilter onChange={panelFilterChanged} />} </div> )} </div> ); } ); SearchControls.displayName = 'SearchControls'; function getRowStyles(theme: GrafanaTheme2, variant = LibraryPanelsSearchVariant.Spacious) { const searchRowContainer = css` display: flex; gap: ${theme.spacing(1)}; flex-grow: 1; flex-direction: row; justify-content: end; `; const searchRowContainerTight = css` ${searchRowContainer}; flex-grow: initial; flex-direction: column; justify-content: normal; `; const filterContainer = css` display: flex; flex-direction: row; margin-left: auto; gap: 4px; `; const filterContainerTight = css` ${filterContainer}; flex-direction: column; margin-left: initial; `; switch (variant) { case LibraryPanelsSearchVariant.Spacious: return { container: searchRowContainer, filterContainer: filterContainer, }; case LibraryPanelsSearchVariant.Tight: return { container: searchRowContainerTight, filterContainer: filterContainerTight, }; } }
Edit
Rename
Chmod
Delete
FILE
FOLDER
INFO
Name
Size
Permission
Action
LibraryPanelsSearch.test.tsx
13334 bytes
0644
LibraryPanelsSearch.tsx
6893 bytes
0644
N4ST4R_ID | Naxtarrr