ManageDashboardsNew.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { css, cx } from '@emotion/css';
  2. import React, { useState } from 'react';
  3. import { useDebounce, useLocalStorage } from 'react-use';
  4. import { GrafanaTheme2 } from '@grafana/data';
  5. import { config } from '@grafana/runtime';
  6. import { Input, useStyles2, Spinner } from '@grafana/ui';
  7. import { contextSrv } from 'app/core/services/context_srv';
  8. import { FolderDTO } from 'app/types';
  9. import { SEARCH_PANELS_LOCAL_STORAGE_KEY } from '../constants';
  10. import { useKeyNavigationListener } from '../hooks/useSearchKeyboardSelection';
  11. import { useSearchQuery } from '../hooks/useSearchQuery';
  12. import { SearchView } from '../page/components/SearchView';
  13. import { DashboardActions } from './DashboardActions';
  14. export interface Props {
  15. folder?: FolderDTO;
  16. }
  17. export const ManageDashboardsNew = React.memo(({ folder }: Props) => {
  18. const styles = useStyles2(getStyles);
  19. // since we don't use "query" from use search... it is not actually loaded from the URL!
  20. const { query, onQueryChange } = useSearchQuery({});
  21. const { onKeyDown, keyboardEvents } = useKeyNavigationListener();
  22. // TODO: we need to refactor DashboardActions to use folder.uid instead
  23. const folderId = folder?.id;
  24. // const folderUid = folder?.uid;
  25. const canSave = folder?.canSave;
  26. const hasEditPermissionInFolders = folder ? canSave : contextSrv.hasEditPermissionInFolders;
  27. let [includePanels, setIncludePanels] = useLocalStorage<boolean>(SEARCH_PANELS_LOCAL_STORAGE_KEY, true);
  28. if (!config.featureToggles.panelTitleSearch) {
  29. includePanels = false;
  30. }
  31. const { isEditor } = contextSrv;
  32. const [inputValue, setInputValue] = useState(query.query ?? '');
  33. const onSearchQueryChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  34. e.preventDefault();
  35. setInputValue(e.currentTarget.value);
  36. };
  37. useDebounce(() => onQueryChange(inputValue), 200, [inputValue]);
  38. return (
  39. <>
  40. <div className={cx(styles.actionBar, 'page-action-bar')}>
  41. <div className={cx(styles.inputWrapper, 'gf-form gf-form--grow m-r-2')}>
  42. <Input
  43. value={inputValue}
  44. onChange={onSearchQueryChange}
  45. onKeyDown={onKeyDown}
  46. autoFocus
  47. spellCheck={false}
  48. placeholder={includePanels ? 'Search for dashboards and panels' : 'Search for dashboards'}
  49. className={styles.searchInput}
  50. suffix={false ? <Spinner /> : null}
  51. />
  52. </div>
  53. <DashboardActions isEditor={isEditor} canEdit={hasEditPermissionInFolders || canSave} folderId={folderId} />
  54. </div>
  55. <SearchView
  56. showManage={isEditor || hasEditPermissionInFolders || canSave}
  57. folderDTO={folder}
  58. queryText={query.query}
  59. onQueryTextChange={(newQueryText) => {
  60. setInputValue(newQueryText);
  61. }}
  62. hidePseudoFolders={true}
  63. includePanels={includePanels!}
  64. setIncludePanels={setIncludePanels}
  65. keyboardEvents={keyboardEvents}
  66. />
  67. </>
  68. );
  69. });
  70. ManageDashboardsNew.displayName = 'ManageDashboardsNew';
  71. export default ManageDashboardsNew;
  72. const getStyles = (theme: GrafanaTheme2) => ({
  73. actionBar: css`
  74. ${theme.breakpoints.down('sm')} {
  75. flex-wrap: wrap;
  76. }
  77. `,
  78. inputWrapper: css`
  79. ${theme.breakpoints.down('sm')} {
  80. margin-right: 0 !important;
  81. }
  82. `,
  83. searchInput: css`
  84. margin-bottom: 6px;
  85. min-height: ${theme.spacing(4)};
  86. `,
  87. unsupported: css`
  88. padding: 10px;
  89. display: flex;
  90. align-items: center;
  91. justify-content: center;
  92. height: 100%;
  93. font-size: 18px;
  94. `,
  95. noResults: css`
  96. padding: ${theme.v1.spacing.md};
  97. background: ${theme.v1.colors.bg2};
  98. font-style: italic;
  99. margin-top: ${theme.v1.spacing.md};
  100. `,
  101. });