mirror of
https://github.com/grafana/grafana.git
synced 2025-02-10 23:55:47 -06:00
Folder: Provide adhoc ui for nested folder creation (#59126)
chore: provide adhoc ui for nested folder creation
This commit is contained in:
parent
4e6b8f658e
commit
7d82a27835
@ -1,10 +1,11 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React from 'react';
|
||||||
import { connect, ConnectedProps } from 'react-redux';
|
import { connect, ConnectedProps } from 'react-redux';
|
||||||
|
|
||||||
import { NavModelItem } from '@grafana/data';
|
import { NavModelItem } from '@grafana/data';
|
||||||
import { config } from '@grafana/runtime';
|
import { config } from '@grafana/runtime';
|
||||||
import { Button, Input, Form, Field } from '@grafana/ui';
|
import { Button, Input, Form, Field } from '@grafana/ui';
|
||||||
import { Page } from 'app/core/components/Page/Page';
|
import { Page } from 'app/core/components/Page/Page';
|
||||||
|
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||||
|
|
||||||
import { validationSrv } from '../../manage-dashboards/services/ValidationSrv';
|
import { validationSrv } from '../../manage-dashboards/services/ValidationSrv';
|
||||||
import { createNewFolder } from '../state/actions';
|
import { createNewFolder } from '../state/actions';
|
||||||
@ -21,16 +22,22 @@ interface FormModel {
|
|||||||
folderName: string;
|
folderName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialFormModel: FormModel = { folderName: '' };
|
|
||||||
|
|
||||||
type Props = OwnProps & ConnectedProps<typeof connector>;
|
type Props = OwnProps & ConnectedProps<typeof connector>;
|
||||||
|
|
||||||
export class NewDashboardsFolder extends PureComponent<Props> {
|
const initialFormModel: FormModel = { folderName: '' };
|
||||||
onSubmit = (formData: FormModel) => {
|
|
||||||
this.props.createNewFolder(formData.folderName);
|
|
||||||
};
|
|
||||||
|
|
||||||
validateFolderName = (folderName: string) => {
|
const pageNav: NavModelItem = {
|
||||||
|
text: 'Create a new folder',
|
||||||
|
subTitle: 'Folders provide a way to group dashboards and alert rules.',
|
||||||
|
breadcrumbs: [{ title: 'Dashboards', url: 'dashboards' }],
|
||||||
|
};
|
||||||
|
|
||||||
|
function NewDashboardsFolder({ createNewFolder }: Props) {
|
||||||
|
const [queryParams] = useQueryParams();
|
||||||
|
const onSubmit = (formData: FormModel) => {
|
||||||
|
createNewFolder(formData.folderName, String(queryParams['folderUid']));
|
||||||
|
};
|
||||||
|
const validateFolderName = (folderName: string) => {
|
||||||
return validationSrv
|
return validationSrv
|
||||||
.validateNewFolderName(folderName)
|
.validateNewFolderName(folderName)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@ -41,41 +48,33 @@ export class NewDashboardsFolder extends PureComponent<Props> {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
pageNav: NavModelItem = {
|
return (
|
||||||
text: 'Create a new folder',
|
<Page navId="dashboards/browse" pageNav={pageNav}>
|
||||||
subTitle: 'Folders provide a way to group dashboards and alert rules.',
|
<Page.Contents>
|
||||||
breadcrumbs: [{ title: 'Dashboards', url: 'dashboards' }],
|
{!config.featureToggles.topnav && <h3>New dashboard folder</h3>}
|
||||||
};
|
<Form defaultValues={initialFormModel} onSubmit={onSubmit}>
|
||||||
|
{({ register, errors }) => (
|
||||||
render() {
|
<>
|
||||||
return (
|
<Field
|
||||||
<Page navId="dashboards/browse" pageNav={this.pageNav}>
|
label="Folder name"
|
||||||
<Page.Contents>
|
invalid={!!errors.folderName}
|
||||||
{!config.featureToggles.topnav && <h3>New dashboard folder</h3>}
|
error={errors.folderName && errors.folderName.message}
|
||||||
<Form defaultValues={initialFormModel} onSubmit={this.onSubmit}>
|
>
|
||||||
{({ register, errors }) => (
|
<Input
|
||||||
<>
|
id="folder-name-input"
|
||||||
<Field
|
{...register('folderName', {
|
||||||
label="Folder name"
|
required: 'Folder name is required.',
|
||||||
invalid={!!errors.folderName}
|
validate: async (v) => await validateFolderName(v),
|
||||||
error={errors.folderName && errors.folderName.message}
|
})}
|
||||||
>
|
/>
|
||||||
<Input
|
</Field>
|
||||||
id="folder-name-input"
|
<Button type="submit">Create</Button>
|
||||||
{...register('folderName', {
|
</>
|
||||||
required: 'Folder name is required.',
|
)}
|
||||||
validate: async (v) => await this.validateFolderName(v),
|
</Form>
|
||||||
})}
|
</Page.Contents>
|
||||||
/>
|
</Page>
|
||||||
</Field>
|
);
|
||||||
<Button type="submit">Create</Button>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Form>
|
|
||||||
</Page.Contents>
|
|
||||||
</Page>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connector(NewDashboardsFolder);
|
export default connector(NewDashboardsFolder);
|
||||||
|
@ -143,9 +143,9 @@ export function addFolderPermission(newItem: NewDashboardAclItem): ThunkResult<v
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createNewFolder(folderName: string): ThunkResult<void> {
|
export function createNewFolder(folderName: string, uid?: string): ThunkResult<void> {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
const newFolder = await getBackendSrv().post('/api/folders', { title: folderName });
|
const newFolder = await getBackendSrv().post('/api/folders', { title: folderName, parentUid: uid });
|
||||||
await contextSrv.fetchUserPermissions();
|
await contextSrv.fetchUserPermissions();
|
||||||
dispatch(notifyApp(createSuccessNotification('Folder Created', 'OK')));
|
dispatch(notifyApp(createSuccessNotification('Folder Created', 'OK')));
|
||||||
locationService.push(locationUtil.stripBaseFromUrl(newFolder.url));
|
locationService.push(locationUtil.stripBaseFromUrl(newFolder.url));
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
|
|
||||||
|
import { config } from '@grafana/runtime';
|
||||||
import { Menu, Dropdown, Button, Icon } from '@grafana/ui';
|
import { Menu, Dropdown, Button, Icon } from '@grafana/ui';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
@ -11,8 +12,13 @@ export interface Props {
|
|||||||
export const DashboardActions: FC<Props> = ({ folderUid, canCreateFolders = false, canCreateDashboards = false }) => {
|
export const DashboardActions: FC<Props> = ({ folderUid, canCreateFolders = false, canCreateDashboards = false }) => {
|
||||||
const actionUrl = (type: string) => {
|
const actionUrl = (type: string) => {
|
||||||
let url = `dashboard/${type}`;
|
let url = `dashboard/${type}`;
|
||||||
|
const isTypeNewFolder = type === 'new_folder';
|
||||||
|
|
||||||
if (folderUid) {
|
if (isTypeNewFolder) {
|
||||||
|
url = `dashboards/folder/new/`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((isTypeNewFolder && config.featureToggles.nestedFolders) || folderUid) {
|
||||||
url += `?folderUid=${folderUid}`;
|
url += `?folderUid=${folderUid}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,7 +29,9 @@ export const DashboardActions: FC<Props> = ({ folderUid, canCreateFolders = fals
|
|||||||
return (
|
return (
|
||||||
<Menu>
|
<Menu>
|
||||||
{canCreateDashboards && <Menu.Item url={actionUrl('new')} label="New Dashboard" />}
|
{canCreateDashboards && <Menu.Item url={actionUrl('new')} label="New Dashboard" />}
|
||||||
{!folderUid && canCreateFolders && <Menu.Item url="dashboards/folder/new" label="New Folder" />}
|
{canCreateFolders && (config.featureToggles.nestedFolders || !folderUid) && (
|
||||||
|
<Menu.Item url={actionUrl('new_folder')} label="New Folder" />
|
||||||
|
)}
|
||||||
{canCreateDashboards && <Menu.Item url={actionUrl('import')} label="Import" />}
|
{canCreateDashboards && <Menu.Item url={actionUrl('import')} label="Import" />}
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user