From 84a8a1aaa6e7b72a5078edcd25d7ac98d759e848 Mon Sep 17 00:00:00 2001 From: Maria Alexandra <239999+axelavargas@users.noreply.github.com> Date: Mon, 23 May 2022 15:03:05 +0200 Subject: [PATCH] Search: Add ManageDashboardNew to integrate new search (#49266) * Search: created ManageDashboardNew to integrate new search * hide pseudo folders in ManageDashboardNew * ManageDashboardNew - Fix overflow table Co-authored-by: Ryan McKinley --- .../search/components/DashboardListPage.tsx | 24 ++++- .../search/components/ManageDashboardsNew.tsx | 89 +++++++++++++++++++ .../search/page/components/FolderSection.tsx | 10 +-- .../search/page/components/FolderView.tsx | 23 +++-- .../search/page/components/SearchView.tsx | 11 ++- 5 files changed, 138 insertions(+), 19 deletions(-) create mode 100644 public/app/features/search/components/ManageDashboardsNew.tsx diff --git a/public/app/features/search/components/DashboardListPage.tsx b/public/app/features/search/components/DashboardListPage.tsx index 5e28073914d..03374885f92 100644 --- a/public/app/features/search/components/DashboardListPage.tsx +++ b/public/app/features/search/components/DashboardListPage.tsx @@ -1,9 +1,10 @@ +import { css } from '@emotion/css'; import React, { FC, memo } from 'react'; import { connect, MapStateToProps } from 'react-redux'; import { useAsync } from 'react-use'; import { NavModel, locationUtil } from '@grafana/data'; -import { locationService } from '@grafana/runtime'; +import { config, locationService } from '@grafana/runtime'; import Page from 'app/core/components/Page/Page'; import { getNavModel } from 'app/core/selectors/navModel'; import { FolderDTO, StoreState } from 'app/types'; @@ -12,6 +13,7 @@ import { GrafanaRouteComponentProps } from '../../../core/navigation/types'; import { loadFolderPage } from '../loaders'; import ManageDashboards from './ManageDashboards'; +import ManageDashboardsNew from './ManageDashboardsNew'; export interface DashboardListPageRouteParams { uid?: string; @@ -44,9 +46,23 @@ export const DashboardListPage: FC = memo(({ navModel, match, location }) return ( - - - + {/*Todo: remove the false to test, or when we feel confident with thsi approach */} + {false && config.featureToggles.panelTitleSearch ? ( + + + + ) : ( + + + + )} ); }); diff --git a/public/app/features/search/components/ManageDashboardsNew.tsx b/public/app/features/search/components/ManageDashboardsNew.tsx new file mode 100644 index 00000000000..9756f9bf99e --- /dev/null +++ b/public/app/features/search/components/ManageDashboardsNew.tsx @@ -0,0 +1,89 @@ +import { css } from '@emotion/css'; +import React, { useState } from 'react'; +import { useDebounce } from 'react-use'; + +import { GrafanaTheme2 } from '@grafana/data'; +import { Input, useStyles2, Spinner } from '@grafana/ui'; +import { contextSrv } from 'app/core/services/context_srv'; +import { FolderDTO } from 'app/types'; + +import { useSearchQuery } from '../hooks/useSearchQuery'; +import { SearchView } from '../page/components/SearchView'; + +import { DashboardActions } from './DashboardActions'; + +export interface Props { + folder?: FolderDTO; +} + +export const ManageDashboardsNew = React.memo(({ folder }: Props) => { + const styles = useStyles2(getStyles); + // since we don't use "query" from use search... it is not actually loaded from the URL! + const { query, onQueryChange } = useSearchQuery({}); + + // TODO: we need to refactor DashboardActions to use folder.uid instead + const folderId = folder?.id; + // const folderUid = folder?.uid; + const canSave = folder?.canSave; + const hasEditPermissionInFolders = folder ? canSave : contextSrv.hasEditPermissionInFolders; + + const { isEditor } = contextSrv; + + const [inputValue, setInputValue] = useState(query.query ?? ''); + const onSearchQueryChange = (e: React.ChangeEvent) => { + e.preventDefault(); + setInputValue(e.currentTarget.value); + }; + useDebounce(() => onQueryChange(inputValue), 200, [inputValue]); + + return ( + <> +
+
+ : null} + /> +
+ +
+ + + + ); +}); + +ManageDashboardsNew.displayName = 'ManageDashboardsNew'; + +export default ManageDashboardsNew; + +const getStyles = (theme: GrafanaTheme2) => ({ + searchInput: css` + margin-bottom: 6px; + min-height: ${theme.spacing(4)}; + `, + unsupported: css` + padding: 10px; + display: flex; + align-items: center; + justify-content: center; + height: 100%; + font-size: 18px; + `, + noResults: css` + padding: ${theme.v1.spacing.md}; + background: ${theme.v1.colors.bg2}; + font-style: italic; + margin-top: ${theme.v1.spacing.md}; + `, +}); diff --git a/public/app/features/search/page/components/FolderSection.tsx b/public/app/features/search/page/components/FolderSection.tsx index fa7df925521..0bff93ac35f 100644 --- a/public/app/features/search/page/components/FolderSection.tsx +++ b/public/app/features/search/page/components/FolderSection.tsx @@ -21,6 +21,7 @@ export interface DashboardSection { selected?: boolean; // not used ? keyboard url?: string; icon?: string; + itemsUIDs?: string[]; // for pseudo folders } interface SectionHeaderProps { @@ -57,12 +58,9 @@ export const FolderSection: FC = ({ location: section.uid, }; if (section.title === 'Starred') { - const stars = await getBackendSrv().get('api/user/stars'); - if (stars.length > 0) { - query = { - uid: stars, // array of UIDs - }; - } + query = { + uid: section.itemsUIDs, // array of UIDs + }; folderUid = undefined; folderTitle = undefined; } else if (section.title === 'Recent') { diff --git a/public/app/features/search/page/components/FolderView.tsx b/public/app/features/search/page/components/FolderView.tsx index 476876432a3..1ba64cffc0e 100644 --- a/public/app/features/search/page/components/FolderView.tsx +++ b/public/app/features/search/page/components/FolderView.tsx @@ -4,6 +4,7 @@ import { useAsync } from 'react-use'; import { GrafanaTheme2 } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; +import { getBackendSrv } from '@grafana/runtime'; import { Spinner, useStyles2 } from '@grafana/ui'; import { GENERAL_FOLDER_UID } from '../../constants'; @@ -12,20 +13,28 @@ import { SearchResultsProps } from '../components/SearchResultsTable'; import { DashboardSection, FolderSection } from './FolderSection'; -type Props = Pick & { tags?: string[] }; -export const FolderView = ({ selection, selectionToggle, onTagSelected, tags }: Props) => { +type Props = Pick & { + tags?: string[]; + hidePseudoFolders?: boolean; +}; +export const FolderView = ({ selection, selectionToggle, onTagSelected, tags, hidePseudoFolders }: Props) => { const styles = useStyles2(getStyles); const results = useAsync(async () => { + const folders: DashboardSection[] = []; + if (!hidePseudoFolders) { + const stars = await getBackendSrv().get('api/user/stars'); + if (stars.length > 0) { + folders.push({ title: 'Starred', icon: 'star', kind: 'query-star', uid: '__starred', itemsUIDs: stars }); + } + folders.push({ title: 'Recent', icon: 'clock', kind: 'query-recent', uid: '__recent' }); + } + folders.push({ title: 'General', url: '/dashboards', kind: 'folder', uid: GENERAL_FOLDER_UID }); + const rsp = await getGrafanaSearcher().search({ query: '*', kind: ['folder'], }); - const folders: DashboardSection[] = [ - { title: 'Recent', icon: 'clock', kind: 'query-recent', uid: '__recent' }, - { title: 'Starred', icon: 'star', kind: 'query-star', uid: '__starred' }, - { title: 'General', url: '/dashboards', kind: 'folder', uid: GENERAL_FOLDER_UID }, // not sure why this is not in the index - ]; for (const row of rsp.view) { folders.push({ title: row.name, diff --git a/public/app/features/search/page/components/SearchView.tsx b/public/app/features/search/page/components/SearchView.tsx index 0a0c710b9d8..0cfd2b42d14 100644 --- a/public/app/features/search/page/components/SearchView.tsx +++ b/public/app/features/search/page/components/SearchView.tsx @@ -26,9 +26,10 @@ type SearchViewProps = { queryText: string; // odd that it is not from query.query showManage: boolean; folderDTO?: FolderDTO; + hidePseudoFolders?: boolean; // Recent + starred }; -export const SearchView = ({ showManage, folderDTO, queryText }: SearchViewProps) => { +export const SearchView = ({ showManage, folderDTO, queryText, hidePseudoFolders }: SearchViewProps) => { const styles = useStyles2(getStyles); const { query, onQueryChange, onTagFilterChange, onTagAdd, onDatasourceChange, onSortChange, onLayoutChange } = @@ -132,7 +133,13 @@ export const SearchView = ({ showManage, folderDTO, queryText }: SearchViewProps ); } return ( - + ); }