From 4b047b62a7d5230cf01b7b16046d26f501532e44 Mon Sep 17 00:00:00 2001 From: Tobias Skarhed <1438972+tskarhed@users.noreply.github.com> Date: Thu, 27 Apr 2023 12:43:20 +0200 Subject: [PATCH] NestedFolders: Button for creating new dashboards and and folders (#67260) * Add CreateNewButton and tests * Add translation support * Move reused phrases to temp common file * Use just a simple button --------- Co-authored-by: joshhunt --- .../BrowseDashboardsPage.tsx | 3 +- .../components/CreateNewButton.test.tsx | 29 ++++++++++++ .../components/CreateNewButton.tsx | 45 +++++++++++++++++++ .../search/components/DashboardActions.tsx | 10 ++--- public/app/features/search/tempI18nPhrases.ts | 16 +++++++ 5 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 public/app/features/browse-dashboards/components/CreateNewButton.test.tsx create mode 100644 public/app/features/browse-dashboards/components/CreateNewButton.tsx diff --git a/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx b/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx index 336e109215f..72fdbe3903b 100644 --- a/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx +++ b/public/app/features/browse-dashboards/BrowseDashboardsPage.tsx @@ -15,6 +15,7 @@ import { skipToken, useGetFolderQuery } from './api/browseDashboardsAPI'; import { BrowseActions } from './components/BrowseActions/BrowseActions'; import { BrowseFilters } from './components/BrowseFilters'; import { BrowseView } from './components/BrowseView'; +import { CreateNewButton } from './components/CreateNewButton'; import { SearchView } from './components/SearchView'; import { useHasSelection } from './state'; @@ -49,7 +50,7 @@ const BrowseDashboardsPage = memo(({ match }: Props) => { const hasSelection = useHasSelection(); return ( - + }> ); + const newButton = screen.getByText('New'); + await userEvent.click(newButton); +} + +describe('NewActionsButton', () => { + it('should display the correct urls with a given folderUID', async () => { + await renderAndOpen('123'); + + expect(screen.getByText('New Dashboard')).toHaveAttribute('href', '/dashboard/new?folderUid=123'); + expect(screen.getByText('New Folder')).toHaveAttribute('href', '/dashboards/folder/new?folderUid=123'); + expect(screen.getByText('Import')).toHaveAttribute('href', '/dashboard/import?folderUid=123'); + }); + + it('should display urls without params when there is no folderUID', async () => { + await renderAndOpen(); + + expect(screen.getByText('New Dashboard')).toHaveAttribute('href', '/dashboard/new'); + expect(screen.getByText('New Folder')).toHaveAttribute('href', '/dashboards/folder/new'); + expect(screen.getByText('Import')).toHaveAttribute('href', '/dashboard/import'); + }); +}); diff --git a/public/app/features/browse-dashboards/components/CreateNewButton.tsx b/public/app/features/browse-dashboards/components/CreateNewButton.tsx new file mode 100644 index 00000000000..01e32bf8fbb --- /dev/null +++ b/public/app/features/browse-dashboards/components/CreateNewButton.tsx @@ -0,0 +1,45 @@ +import React from 'react'; + +import { Button, Dropdown, Icon, Menu, MenuItem } from '@grafana/ui'; +import { + getNewDashboardPhrase, + getNewFolderPhrase, + getImportPhrase, + getNewPhrase, +} from 'app/features/search/tempI18nPhrases'; + +interface Props { + /** + * Pass a folder UID in which the dashboard or folder will be created + */ + inFolder?: string; +} + +export function CreateNewButton({ inFolder }: Props) { + const newMenu = ( + + + + + + ); + + return ( + + + + ); +} + +/** + * + * @param url without any parameters + * @param folderUid folder id + * @returns url with paramter if folder is present + */ +function addFolderUidToUrl(url: string, folderUid: string | undefined) { + return folderUid ? url + '?folderUid=' + folderUid : url; +} diff --git a/public/app/features/search/components/DashboardActions.tsx b/public/app/features/search/components/DashboardActions.tsx index 40ee16db4f7..12dc125b50e 100644 --- a/public/app/features/search/components/DashboardActions.tsx +++ b/public/app/features/search/components/DashboardActions.tsx @@ -2,10 +2,10 @@ import React, { useMemo, useState } from 'react'; import { config, reportInteraction } from '@grafana/runtime'; import { Menu, Dropdown, Button, Icon, HorizontalGroup } from '@grafana/ui'; -import { t } from 'app/core/internationalization'; import { FolderDTO } from 'app/types'; import { MoveToFolderModal } from '../page/components/MoveToFolderModal'; +import { getImportPhrase, getNewDashboardPhrase, getNewFolderPhrase, getNewPhrase } from '../tempI18nPhrases'; export interface Props { folder: FolderDTO | undefined; @@ -43,7 +43,7 @@ export const DashboardActions = ({ folder, canCreateFolders = false, canCreateDa {canCreateDashboards && ( reportInteraction('grafana_menu_item_clicked', { url: actionUrl('new'), from: '/dashboards' }) } @@ -52,7 +52,7 @@ export const DashboardActions = ({ folder, canCreateFolders = false, canCreateDa {canCreateFolders && (config.featureToggles.nestedFolders || !folder?.uid) && ( reportInteraction('grafana_menu_item_clicked', { url: actionUrl('new_folder'), from: '/dashboards' }) } @@ -61,7 +61,7 @@ export const DashboardActions = ({ folder, canCreateFolders = false, canCreateDa {canCreateDashboards && ( reportInteraction('grafana_menu_item_clicked', { url: actionUrl('import'), from: '/dashboards' }) } @@ -82,7 +82,7 @@ export const DashboardActions = ({ folder, canCreateFolders = false, canCreateDa )} diff --git a/public/app/features/search/tempI18nPhrases.ts b/public/app/features/search/tempI18nPhrases.ts index 07c2abbf0ef..83b99bf2570 100644 --- a/public/app/features/search/tempI18nPhrases.ts +++ b/public/app/features/search/tempI18nPhrases.ts @@ -8,3 +8,19 @@ export function getSearchPlaceholder(includePanels = false) { ? t('search.search-input.include-panels-placeholder', 'Search for dashboards, folders, and panels') : t('search.search-input.placeholder', 'Search for dashboards and folders'); } + +export function getNewDashboardPhrase() { + return t('search.dashboard-actions.new-dashboard', 'New Dashboard'); +} + +export function getNewFolderPhrase() { + return t('search.dashboard-actions.new-folder', 'New Folder'); +} + +export function getImportPhrase() { + return t('search.dashboard-actions.import', 'Import'); +} + +export function getNewPhrase() { + return t('search.dashboard-actions.new', 'New'); +}