Fix flaky save button validation in SaveDashboardAsForm (#112526)

Fix flakiness in save as dashboard form
This commit is contained in:
Dominik Prokop
2025-10-17 08:50:39 -06:00
committed by GitHub
parent 7c6afeabec
commit 7f99cce8c8
@@ -1,5 +1,5 @@
import debounce from 'debounce-promise';
import { ChangeEvent, useState } from 'react';
import { ChangeEvent, useState, useEffect } from 'react';
import { UseFormSetValue, useForm } from 'react-hook-form';
import { selectors } from '@grafana/e2e-selectors';
@@ -30,7 +30,7 @@ export interface Props {
export function SaveDashboardAsForm({ dashboard, changeInfo }: Props) {
const { changedSaveModel } = changeInfo;
const { register, handleSubmit, setValue, formState, getValues, watch } = useForm<SaveDashboardAsFormDTO>({
const { register, handleSubmit, setValue, formState, getValues, watch, trigger } = useForm<SaveDashboardAsFormDTO>({
mode: 'onBlur',
defaultValues: {
title: changeInfo.isNew ? changedSaveModel.title! : `${changedSaveModel.title} Copy`,
@@ -49,7 +49,11 @@ export function SaveDashboardAsForm({ dashboard, changeInfo }: Props) {
const { state, onSaveDashboard } = useSaveDashboard(false);
const [contentSent, setContentSent] = useState<{ title?: string; folderUid?: string }>({});
const [hasFolderChanged, setHasFolderChanged] = useState(false);
// Validate title on form mount to catch invalid default values
useEffect(() => {
trigger('title');
}, [trigger]);
const onSave = async (overwrite: boolean) => {
const data = getValues();
@@ -84,12 +88,11 @@ export function SaveDashboardAsForm({ dashboard, changeInfo }: Props) {
);
const saveButton = (overwrite: boolean) => {
const showSaveButton = !isValid && hasFolderChanged ? true : isValid;
const isTitleValidating = !!validatingFields.title;
return (
<SaveButton
isValid={showSaveButton && !isTitleValidating}
isValid={isValid && !isTitleValidating}
isLoading={state.loading}
onSave={onSave}
overwrite={overwrite}
@@ -160,8 +163,6 @@ export function SaveDashboardAsForm({ dashboard, changeInfo }: Props) {
<FolderPicker
onChange={async (uid: string | undefined, title: string | undefined) => {
setValue('folder', { uid, title });
const folderUid = dashboard.state.meta.folderUid;
setHasFolderChanged(uid !== folderUid);
const meta = await getProvisionedMeta(uid);
dashboard.setState({
meta: {
@@ -169,6 +170,8 @@ export function SaveDashboardAsForm({ dashboard, changeInfo }: Props) {
folderUid: uid,
},
});
// Re-validate title when folder changes to check for duplicates in new folder
trigger('title');
}}
value={formValues.folder?.uid}
/>