mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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 <josh@trtr.co>
This commit is contained in:
parent
f28c962dc8
commit
4b047b62a7
@ -15,6 +15,7 @@ import { skipToken, useGetFolderQuery } from './api/browseDashboardsAPI';
|
|||||||
import { BrowseActions } from './components/BrowseActions/BrowseActions';
|
import { BrowseActions } from './components/BrowseActions/BrowseActions';
|
||||||
import { BrowseFilters } from './components/BrowseFilters';
|
import { BrowseFilters } from './components/BrowseFilters';
|
||||||
import { BrowseView } from './components/BrowseView';
|
import { BrowseView } from './components/BrowseView';
|
||||||
|
import { CreateNewButton } from './components/CreateNewButton';
|
||||||
import { SearchView } from './components/SearchView';
|
import { SearchView } from './components/SearchView';
|
||||||
import { useHasSelection } from './state';
|
import { useHasSelection } from './state';
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ const BrowseDashboardsPage = memo(({ match }: Props) => {
|
|||||||
const hasSelection = useHasSelection();
|
const hasSelection = useHasSelection();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page navId="dashboards/browse" pageNav={navModel}>
|
<Page navId="dashboards/browse" pageNav={navModel} actions={<CreateNewButton inFolder={folderUID} />}>
|
||||||
<Page.Contents className={styles.pageContents}>
|
<Page.Contents className={styles.pageContents}>
|
||||||
<FilterInput
|
<FilterInput
|
||||||
placeholder={getSearchPlaceholder(searchState.includePanels)}
|
placeholder={getSearchPlaceholder(searchState.includePanels)}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { CreateNewButton } from './CreateNewButton';
|
||||||
|
|
||||||
|
async function renderAndOpen(folderUID?: string) {
|
||||||
|
render(<CreateNewButton inFolder={folderUID} />);
|
||||||
|
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');
|
||||||
|
});
|
||||||
|
});
|
@ -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 = (
|
||||||
|
<Menu>
|
||||||
|
<MenuItem url={addFolderUidToUrl('/dashboard/new', inFolder)} label={getNewDashboardPhrase()} />
|
||||||
|
<MenuItem url={addFolderUidToUrl('/dashboards/folder/new', inFolder)} label={getNewFolderPhrase()} />
|
||||||
|
<MenuItem url={addFolderUidToUrl('/dashboard/import', inFolder)} label={getImportPhrase()} />
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dropdown overlay={newMenu}>
|
||||||
|
<Button>
|
||||||
|
{getNewPhrase()}
|
||||||
|
<Icon name="angle-down" />
|
||||||
|
</Button>
|
||||||
|
</Dropdown>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @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;
|
||||||
|
}
|
@ -2,10 +2,10 @@ import React, { useMemo, useState } from 'react';
|
|||||||
|
|
||||||
import { config, reportInteraction } from '@grafana/runtime';
|
import { config, reportInteraction } from '@grafana/runtime';
|
||||||
import { Menu, Dropdown, Button, Icon, HorizontalGroup } from '@grafana/ui';
|
import { Menu, Dropdown, Button, Icon, HorizontalGroup } from '@grafana/ui';
|
||||||
import { t } from 'app/core/internationalization';
|
|
||||||
import { FolderDTO } from 'app/types';
|
import { FolderDTO } from 'app/types';
|
||||||
|
|
||||||
import { MoveToFolderModal } from '../page/components/MoveToFolderModal';
|
import { MoveToFolderModal } from '../page/components/MoveToFolderModal';
|
||||||
|
import { getImportPhrase, getNewDashboardPhrase, getNewFolderPhrase, getNewPhrase } from '../tempI18nPhrases';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
folder: FolderDTO | undefined;
|
folder: FolderDTO | undefined;
|
||||||
@ -43,7 +43,7 @@ export const DashboardActions = ({ folder, canCreateFolders = false, canCreateDa
|
|||||||
{canCreateDashboards && (
|
{canCreateDashboards && (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
url={actionUrl('new')}
|
url={actionUrl('new')}
|
||||||
label={t('search.dashboard-actions.new-dashboard', 'New Dashboard')}
|
label={getNewDashboardPhrase()}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
reportInteraction('grafana_menu_item_clicked', { url: actionUrl('new'), from: '/dashboards' })
|
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) && (
|
{canCreateFolders && (config.featureToggles.nestedFolders || !folder?.uid) && (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
url={actionUrl('new_folder')}
|
url={actionUrl('new_folder')}
|
||||||
label={t('search.dashboard-actions.new-folder', 'New Folder')}
|
label={getNewFolderPhrase()}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
reportInteraction('grafana_menu_item_clicked', { url: actionUrl('new_folder'), from: '/dashboards' })
|
reportInteraction('grafana_menu_item_clicked', { url: actionUrl('new_folder'), from: '/dashboards' })
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ export const DashboardActions = ({ folder, canCreateFolders = false, canCreateDa
|
|||||||
{canCreateDashboards && (
|
{canCreateDashboards && (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
url={actionUrl('import')}
|
url={actionUrl('import')}
|
||||||
label={t('search.dashboard-actions.import', 'Import')}
|
label={getImportPhrase()}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
reportInteraction('grafana_menu_item_clicked', { url: actionUrl('import'), from: '/dashboards' })
|
reportInteraction('grafana_menu_item_clicked', { url: actionUrl('import'), from: '/dashboards' })
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ export const DashboardActions = ({ folder, canCreateFolders = false, canCreateDa
|
|||||||
)}
|
)}
|
||||||
<Dropdown overlay={MenuActions} placement="bottom-start">
|
<Dropdown overlay={MenuActions} placement="bottom-start">
|
||||||
<Button variant="primary">
|
<Button variant="primary">
|
||||||
{t('search.dashboard-actions.new', 'New')}
|
{getNewPhrase()}
|
||||||
<Icon name="angle-down" />
|
<Icon name="angle-down" />
|
||||||
</Button>
|
</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
@ -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.include-panels-placeholder', 'Search for dashboards, folders, and panels')
|
||||||
: t('search.search-input.placeholder', 'Search for dashboards and folders');
|
: 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');
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user