Folders: Fix create button disable on submit & duplication logic (#109696)
This commit is contained in:
@@ -48,9 +48,11 @@ function FolderCreationModal({
|
||||
const styles = useStyles2(getStyles);
|
||||
const notifyApp = useAppNotification();
|
||||
const [title, setTitle] = useState('');
|
||||
const [isCreatingFolder, setIsCreatingFolder] = useState(false);
|
||||
const [createFolder] = useNewFolderMutation();
|
||||
|
||||
const onSubmit = async () => {
|
||||
setIsCreatingFolder(true);
|
||||
const { data, error } = await createFolder({ title });
|
||||
|
||||
if (error) {
|
||||
@@ -59,6 +61,7 @@ function FolderCreationModal({
|
||||
onCreate({ title: data.title, uid: data.uid });
|
||||
notifyApp.success('Folder created');
|
||||
}
|
||||
setIsCreatingFolder(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -93,7 +96,7 @@ function FolderCreationModal({
|
||||
</Button>
|
||||
<Button
|
||||
onClick={onSubmit}
|
||||
disabled={!title}
|
||||
disabled={!title || isCreatingFolder}
|
||||
data-testid={selectors.components.AlertRules.newFolderNameCreateButton}
|
||||
>
|
||||
<Trans i18nKey="alerting.create-new-folder.folder.create">Create</Trans>
|
||||
|
||||
@@ -123,7 +123,11 @@ export default function CreateNewButton({
|
||||
{parentFolder?.managedBy === ManagerKind.Repo || isProvisionedInstance ? (
|
||||
<NewProvisionedFolderForm onDismiss={() => setShowNewFolderDrawer(false)} parentFolder={parentFolder} />
|
||||
) : (
|
||||
<NewFolderForm onConfirm={onCreateFolder} onCancel={() => setShowNewFolderDrawer(false)} />
|
||||
<NewFolderForm
|
||||
onConfirm={onCreateFolder}
|
||||
onCancel={() => setShowNewFolderDrawer(false)}
|
||||
parentFolder={parentFolder}
|
||||
/>
|
||||
)}
|
||||
</Drawer>
|
||||
)}
|
||||
|
||||
@@ -3,12 +3,14 @@ import { useForm } from 'react-hook-form';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { Trans, t } from '@grafana/i18n';
|
||||
import { Button, Input, Field, Stack } from '@grafana/ui';
|
||||
import { FolderDTO } from 'app/types/folders';
|
||||
|
||||
import { validationSrv } from '../../manage-dashboards/services/ValidationSrv';
|
||||
|
||||
interface Props {
|
||||
onConfirm: (folderName: string) => void;
|
||||
onCancel: () => void;
|
||||
parentFolder?: FolderDTO;
|
||||
}
|
||||
|
||||
interface FormModel {
|
||||
@@ -17,11 +19,11 @@ interface FormModel {
|
||||
|
||||
const initialFormModel: FormModel = { folderName: '' };
|
||||
|
||||
export function NewFolderForm({ onCancel, onConfirm }: Props) {
|
||||
export function NewFolderForm({ onCancel, onConfirm, parentFolder }: Props) {
|
||||
const {
|
||||
handleSubmit,
|
||||
register,
|
||||
formState: { errors },
|
||||
formState: { errors, isSubmitting },
|
||||
} = useForm<FormModel>({ defaultValues: initialFormModel });
|
||||
|
||||
const translatedFolderNameRequiredPhrase = t(
|
||||
@@ -48,7 +50,7 @@ export function NewFolderForm({ onCancel, onConfirm }: Props) {
|
||||
defaultValue={initialFormModel.folderName}
|
||||
{...register('folderName', {
|
||||
required: translatedFolderNameRequiredPhrase,
|
||||
validate: async (v) => await validateFolderName(v),
|
||||
validate: async (v) => await validateFolderName(v, parentFolder?.uid),
|
||||
})}
|
||||
/>
|
||||
</Field>
|
||||
@@ -56,7 +58,7 @@ export function NewFolderForm({ onCancel, onConfirm }: Props) {
|
||||
<Button variant="secondary" fill="outline" onClick={onCancel}>
|
||||
<Trans i18nKey="browse-dashboards.new-folder-form.cancel-label">Cancel</Trans>
|
||||
</Button>
|
||||
<Button type="submit">
|
||||
<Button type="submit" disabled={isSubmitting}>
|
||||
<Trans i18nKey="browse-dashboards.new-folder-form.create-label">Create</Trans>
|
||||
</Button>
|
||||
</Stack>
|
||||
@@ -64,9 +66,9 @@ export function NewFolderForm({ onCancel, onConfirm }: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
export async function validateFolderName(folderName: string) {
|
||||
export async function validateFolderName(folderName: string, parentFolderUid?: string) {
|
||||
try {
|
||||
await validationSrv.validateNewFolderName(folderName);
|
||||
await validationSrv.validateNewFolderName(folderName, parentFolderUid);
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
|
||||
@@ -24,18 +24,28 @@ export class ValidationSrv {
|
||||
);
|
||||
}
|
||||
|
||||
validateNewFolderName(name?: string) {
|
||||
return this.validate(
|
||||
this.rootName,
|
||||
name,
|
||||
t(
|
||||
'manage-dashboards.validation-srv.message-same-name-general',
|
||||
'A folder or dashboard in the general folder with the same name already exists'
|
||||
)
|
||||
);
|
||||
validateNewFolderName(name?: string, parentFolderUid?: string) {
|
||||
const validationMessage = parentFolderUid
|
||||
? t(
|
||||
'manage-dashboards.validation-srv.message-same-name-current-folder',
|
||||
'A dashboard or a folder with the same name already exists in the current folder'
|
||||
)
|
||||
: t(
|
||||
'manage-dashboards.validation-srv.message-same-name-general',
|
||||
'A folder or dashboard with the same name already exists in the root folder'
|
||||
);
|
||||
|
||||
return this.validate(parentFolderUid || this.rootName, name, validationMessage);
|
||||
}
|
||||
|
||||
private async validate(folderUID: string, name: string | undefined, existingErrorMessage: string) {
|
||||
private async validate(
|
||||
/** Folder in which to validate newly created resource */
|
||||
folderUID: string,
|
||||
/** Name of the resource being created */
|
||||
name: string | undefined,
|
||||
/** Error message to throw if the resource already exists */
|
||||
existingErrorMessage: string
|
||||
) {
|
||||
name = (name || '').trim();
|
||||
const nameLowerCased = name.toLowerCase();
|
||||
|
||||
@@ -59,7 +69,7 @@ export class ValidationSrv {
|
||||
const searcher = getGrafanaSearcher();
|
||||
|
||||
const dashboardResults = await searcher.search({
|
||||
kind: ['dashboard'],
|
||||
kind: ['dashboard', 'folder'],
|
||||
query: name,
|
||||
location: folderUID || 'general',
|
||||
});
|
||||
|
||||
@@ -9755,7 +9755,8 @@
|
||||
"message-name-required": "Name is required",
|
||||
"message-reserved-name": "This is a reserved name and cannot be used for a folder.",
|
||||
"message-same-name": "A dashboard or a folder with the same name already exists",
|
||||
"message-same-name-general": "A folder or dashboard in the general folder with the same name already exists"
|
||||
"message-same-name-current-folder": "A dashboard or a folder with the same name already exists in the current folder",
|
||||
"message-same-name-general": "A folder or dashboard with the same name already exists in the root folder"
|
||||
}
|
||||
},
|
||||
"metric-select": {
|
||||
|
||||
Reference in New Issue
Block a user