From b803e645de2042016088a7fac66995cfbbfa3237 Mon Sep 17 00:00:00 2001 From: Hana Xu Date: Mon, 2 Feb 2026 17:07:38 -0500 Subject: [PATCH 1/6] disable restore button if first backup hasn't been completed yet --- .../DatabaseDetail/DatabaseBackups/DatabaseBackups.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseBackups/DatabaseBackups.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseBackups/DatabaseBackups.tsx index deae3d8f4da..0a676b3684c 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseBackups/DatabaseBackups.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseBackups/DatabaseBackups.tsx @@ -315,10 +315,12 @@ export const DatabaseBackups = () => { buttonType="primary" data-qa-settings-button="restore" disabled={ - versionOption === 'dateTime' && - (!date || !time || !!errors.time) + Boolean(unableToRestoreCopy) || + (versionOption === 'dateTime' && + (!date || !time || !!errors.time)) } onClick={() => setIsRestoreDialogOpen(true)} + tooltipText={unableToRestoreCopy} > Restore From 9621632e83845329500704abd35fe9ba92b51842 Mon Sep 17 00:00:00 2001 From: Hana Xu Date: Mon, 2 Feb 2026 17:13:52 -0500 Subject: [PATCH 2/6] clear errors on close for backups dialog --- .../DatabaseBackups/DatabaseBackupsDialog.tsx | 57 ++++++++++--------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseBackups/DatabaseBackupsDialog.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseBackups/DatabaseBackupsDialog.tsx index f6112e22157..019cf33f2e8 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseBackups/DatabaseBackupsDialog.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseBackups/DatabaseBackupsDialog.tsx @@ -3,7 +3,6 @@ import { ActionsPanel, Dialog, Notice, Typography } from '@linode/ui'; import { useNavigate } from '@tanstack/react-router'; import { useSnackbar } from 'notistack'; import * as React from 'react'; -import { useState } from 'react'; import { useFormContext, useWatch } from 'react-hook-form'; import { getAPIErrorOrDefault } from 'src/utilities/errorUtils'; @@ -24,7 +23,6 @@ export const DatabaseBackupsDialog = (props: Props) => { const { database, onClose, open } = props; const navigate = useNavigate(); const { enqueueSnackbar } = useSnackbar(); - const [isRestoring, setIsRestoring] = useState(false); const { control } = useFormContext(); const [date, time, region] = useWatch({ @@ -34,19 +32,25 @@ export const DatabaseBackupsDialog = (props: Props) => { const formattedDate = toFormattedDate(date, time); - const { error, mutateAsync: restore } = useRestoreFromBackupMutation( - database.engine, - { - fork: toDatabaseFork(database.id, date, time), - region, - // Assign same VPC when forking to the same region, otherwise set VPC to null - private_network: - database.region === region ? database.private_network : null, - } - ); + const { + error, + mutateAsync: restore, + reset, + isPending, + } = useRestoreFromBackupMutation(database.engine, { + fork: toDatabaseFork(database.id, date, time), + region, + // Assign same VPC when forking to the same region, otherwise set VPC to null + private_network: + database.region === region ? database.private_network : null, + }); + + const _onClose = () => { + onClose(); + reset(); + }; const handleRestoreDatabase = () => { - setIsRestoring(true); restore().then((database: Database) => { navigate({ to: `/databases/$engine/$databaseId`, @@ -58,7 +62,8 @@ export const DatabaseBackupsDialog = (props: Props) => { enqueueSnackbar('Your database is being restored.', { variant: 'success', }); - onClose(); + _onClose(); + reset(); }); }; @@ -67,11 +72,20 @@ export const DatabaseBackupsDialog = (props: Props) => { return ( + {error ? ( + + ) : null} {isClusterWithVPCAndForkingToDifferentRegion && ( // Show warning when forking a cluster with VPC to a different region The database cluster is currently assigned to a VPC. When you restore @@ -91,13 +105,13 @@ export const DatabaseBackupsDialog = (props: Props) => { primaryButtonProps={{ 'data-testid': 'submit', label: 'Restore', - loading: isRestoring, + loading: isPending, onClick: handleRestoreDatabase, }} secondaryButtonProps={{ 'data-testid': 'cancel', label: 'Cancel', - onClick: onClose, + onClick: _onClose, }} sx={{ display: 'flex', @@ -105,15 +119,6 @@ export const DatabaseBackupsDialog = (props: Props) => { paddingBottom: '0', }} /> - {error ? ( - - ) : null} ); }; From 7387645d7a5b3a2ffe9e096eaee8066e15d7d98d Mon Sep 17 00:00:00 2001 From: Hana Xu Date: Mon, 2 Feb 2026 17:18:19 -0500 Subject: [PATCH 3/6] clear errors on delete dialog close --- .../DatabaseSettings/DatabaseSettings.tsx | 2 +- .../DatabaseSettingsDeleteClusterDialog.tsx | 62 ++++++++++--------- .../DatabaseLanding/DatabaseLandingTable.tsx | 2 +- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSettings/DatabaseSettings.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSettings/DatabaseSettings.tsx index d9b8c332039..7af56886759 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSettings/DatabaseSettings.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSettings/DatabaseSettings.tsx @@ -22,7 +22,7 @@ import { useFlags } from 'src/hooks/useFlags'; import AccessControls from '../AccessControls'; import { useDatabaseDetailContext } from '../DatabaseDetailContext'; -import DatabaseSettingsDeleteClusterDialog from './DatabaseSettingsDeleteClusterDialog'; +import { DatabaseSettingsDeleteClusterDialog } from './DatabaseSettingsDeleteClusterDialog'; import { DatabaseSettingsMaintenance } from './DatabaseSettingsMaintenance'; import DatabaseSettingsMenuItem from './DatabaseSettingsMenuItem'; import DatabaseSettingsResetPasswordDialog from './DatabaseSettingsResetPasswordDialog'; diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSettings/DatabaseSettingsDeleteClusterDialog.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSettings/DatabaseSettingsDeleteClusterDialog.tsx index 620707f3244..4ccf79ce2f0 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSettings/DatabaseSettingsDeleteClusterDialog.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseSettings/DatabaseSettingsDeleteClusterDialog.tsx @@ -17,35 +17,33 @@ interface Props { open: boolean; } -export const DatabaseSettingsDeleteClusterDialog: React.FC = (props) => { +export const DatabaseSettingsDeleteClusterDialog = (props: Props) => { const { databaseEngine, databaseID, databaseLabel, onClose, open } = props; const { enqueueSnackbar } = useSnackbar(); - const { mutateAsync: deleteDatabase } = useDeleteDatabaseMutation( - databaseEngine, - databaseID - ); - const defaultError = 'There was an error deleting this Database Cluster.'; - const [error, setError] = React.useState(''); - const [isLoading, setIsLoading] = React.useState(false); + const { + mutateAsync: deleteDatabase, + error, + isPending, + reset, + } = useDeleteDatabaseMutation(databaseEngine, databaseID); const navigate = useNavigate(); + const _onClose = () => { + onClose(); + reset(); + }; + const onDeleteCluster = () => { - setIsLoading(true); - deleteDatabase() - .then(() => { - setIsLoading(false); - enqueueSnackbar('Database Cluster deleted successfully.', { - variant: 'success', - }); - onClose(); - navigate({ - to: '/databases', - }); - }) - .catch((e) => { - setIsLoading(false); - setError(getAPIErrorOrDefault(e, defaultError)[0].reason); + deleteDatabase().then(() => { + enqueueSnackbar('Database Cluster deleted successfully.', { + variant: 'success', }); + _onClose(); + reset(); + navigate({ + to: '/databases', + }); + }); }; return ( @@ -59,13 +57,23 @@ export const DatabaseSettingsDeleteClusterDialog: React.FC = (props) => { }} expand label={'Cluster Name'} - loading={isLoading} + loading={isPending} onClick={onDeleteCluster} - onClose={onClose} + onClose={_onClose} open={open} title={`Delete Database Cluster ${databaseLabel}`} > - {error ? : null} + {error ? ( + + ) : null} Warning: Deleting your entire database will delete @@ -76,5 +84,3 @@ export const DatabaseSettingsDeleteClusterDialog: React.FC = (props) => { ); }; - -export default DatabaseSettingsDeleteClusterDialog; diff --git a/packages/manager/src/features/Databases/DatabaseLanding/DatabaseLandingTable.tsx b/packages/manager/src/features/Databases/DatabaseLanding/DatabaseLandingTable.tsx index dba7dd1599a..9bb985eed80 100644 --- a/packages/manager/src/features/Databases/DatabaseLanding/DatabaseLandingTable.tsx +++ b/packages/manager/src/features/Databases/DatabaseLanding/DatabaseLandingTable.tsx @@ -11,7 +11,7 @@ import { import React from 'react'; import { TableRowEmpty } from 'src/components/TableRowEmpty/TableRowEmpty'; -import DatabaseSettingsDeleteClusterDialog from 'src/features/Databases/DatabaseDetail/DatabaseSettings/DatabaseSettingsDeleteClusterDialog'; +import { DatabaseSettingsDeleteClusterDialog } from 'src/features/Databases/DatabaseDetail/DatabaseSettings/DatabaseSettingsDeleteClusterDialog'; import DatabaseSettingsResetPasswordDialog from 'src/features/Databases/DatabaseDetail/DatabaseSettings/DatabaseSettingsResetPasswordDialog'; import { ManageAccessControlDrawer } from 'src/features/Databases/DatabaseDetail/ManageAccessControlDrawer'; import DatabaseLogo from 'src/features/Databases/DatabaseLanding/DatabaseLogo'; From 04f3e3183fb83520e38ba87b70b4e827e322f072 Mon Sep 17 00:00:00 2001 From: Hana Xu Date: Tue, 3 Feb 2026 10:25:40 -0500 Subject: [PATCH 4/6] Added changeset: DBaaS Backup / delete dialog bugs --- packages/manager/.changeset/pr-13355-fixed-1770132340383.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/manager/.changeset/pr-13355-fixed-1770132340383.md diff --git a/packages/manager/.changeset/pr-13355-fixed-1770132340383.md b/packages/manager/.changeset/pr-13355-fixed-1770132340383.md new file mode 100644 index 00000000000..3086aedc887 --- /dev/null +++ b/packages/manager/.changeset/pr-13355-fixed-1770132340383.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Fixed +--- + +DBaaS Backup / delete dialog bugs ([#13355](https://github.com/linode/manager/pull/13355)) From ad543de39e370be099ead947e8d814b9f388f5bc Mon Sep 17 00:00:00 2001 From: Hana Xu Date: Tue, 3 Feb 2026 17:24:43 -0500 Subject: [PATCH 5/6] fix advanced configuration option removal --- .../DatabaseAdvancedConfigurationDrawer.tsx | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseAdvancedConfiguration/DatabaseAdvancedConfigurationDrawer.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseAdvancedConfiguration/DatabaseAdvancedConfigurationDrawer.tsx index e38b1542747..00379b6243b 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseAdvancedConfiguration/DatabaseAdvancedConfigurationDrawer.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseAdvancedConfiguration/DatabaseAdvancedConfigurationDrawer.tsx @@ -15,13 +15,7 @@ import Grid from '@mui/material/Grid'; import { Button } from 'akamai-cds-react-components'; import { enqueueSnackbar } from 'notistack'; import React, { useEffect, useMemo, useState } from 'react'; -import { - Controller, - get, - useFieldArray, - useForm, - useWatch, -} from 'react-hook-form'; +import { Controller, get, useFieldArray, useForm } from 'react-hook-form'; import type { SubmitHandler } from 'react-hook-form'; import { Link } from 'src/components/Link'; @@ -101,8 +95,6 @@ export const DatabaseAdvancedConfigurationDrawer = (props: Props) => { name: 'configs', }); - const configs = useWatch({ control, name: 'configs' }); - useEffect(() => { if (existingConfigurations.length > 0 || open) { reset({ configs: existingConfigurations }); @@ -212,12 +204,12 @@ export const DatabaseAdvancedConfigurationDrawer = (props: Props) => { )} - {!isLoading && configs.length === 0 && ( + {!isLoading && fields.length === 0 && ( No advanced configurations have been added. )} - {configs.map((config, index) => ( + {fields.map((config, index) => ( { Date: Tue, 3 Feb 2026 17:26:38 -0500 Subject: [PATCH 6/6] feedback --- .../DatabaseDetail/DatabaseBackups/DatabaseBackupsDialog.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseBackups/DatabaseBackupsDialog.tsx b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseBackups/DatabaseBackupsDialog.tsx index 019cf33f2e8..ffdeb40c111 100644 --- a/packages/manager/src/features/Databases/DatabaseDetail/DatabaseBackups/DatabaseBackupsDialog.tsx +++ b/packages/manager/src/features/Databases/DatabaseDetail/DatabaseBackups/DatabaseBackupsDialog.tsx @@ -63,7 +63,6 @@ export const DatabaseBackupsDialog = (props: Props) => { variant: 'success', }); _onClose(); - reset(); }); }; @@ -77,7 +76,7 @@ export const DatabaseBackupsDialog = (props: Props) => { subtitle={formattedDate && `From ${formattedDate} (UTC)`} title={`Restore ${database.label}`} > - {error ? ( + {error && ( { } variant="error" /> - ) : null} + )} {isClusterWithVPCAndForkingToDifferentRegion && ( // Show warning when forking a cluster with VPC to a different region The database cluster is currently assigned to a VPC. When you restore