diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/Restore/Restore.service.ts b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/Restore/Restore.service.ts index 97cb6508bb446..34c7469d8aa8d 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/Restore/Restore.service.ts +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/Restore/Restore.service.ts @@ -1,18 +1,8 @@ import { SelectableValue } from '@grafana/data'; import { DBClusterService } from '../../DBCluster.service'; -import { DBaaSBackupService } from '../DBaaSBackups/DBaaSBackups.service'; export const RestoreService = { - async loadBackupArtifacts(locationId: string): Promise>> { - const backupArtifactsResponse = await DBaaSBackupService.list(locationId); - - return backupArtifactsResponse.map((backup) => ({ - label: backup.key, - value: backup.key, - })); - }, - async loadSecretsNames(k8sClusterName: string): Promise>> { const secretsResponse = await DBClusterService.getDBClusterSecrets(k8sClusterName); const secrets = secretsResponse?.secrets || []; diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/Restore/Restore.test.tsx b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/Restore/Restore.test.tsx index 010b3cd248549..e22706a9fb3d7 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/Restore/Restore.test.tsx +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/Restore/Restore.test.tsx @@ -58,7 +58,7 @@ describe('DBaaS DBCluster creation Restore section ::', () => { expect(screen.getByTestId('toggle-scheduled-restore')).toBeInTheDocument(); const checkbox = screen.getByTestId('toggle-scheduled-restore'); await waitFor(() => fireEvent.click(checkbox)); - expect(screen.getByTestId('backupArtifact-field-container')).toBeInTheDocument(); + expect(screen.getByTestId('backup-select-wrapper')).toBeInTheDocument(); }); it('shows secrets field if kubernetesCluster name exists in form', async () => { await waitFor(() => diff --git a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/Restore/Restore.tsx b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/Restore/Restore.tsx index 37da368be0b6e..04b182c436cb9 100644 --- a/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/Restore/Restore.tsx +++ b/public/app/percona/dbaas/components/DBCluster/EditDBClusterPage/Restore/Restore.tsx @@ -1,13 +1,14 @@ -import React, { FC, useState } from 'react'; +import React, { FC, useState, useEffect } from 'react'; import { Field } from 'react-final-form'; import { FieldSet, Switch, useStyles } from '@grafana/ui'; import { AsyncSelectFieldCore } from 'app/percona/shared/components/Form/AsyncSelectFieldCore'; +import { fetchBackupArtifacts } from 'app/percona/shared/core/reducers/backups/backupArtifacts'; import { validators } from 'app/percona/shared/helpers/validatorsForm'; +import { useDispatch, useSelector } from 'app/types'; -import { useSelector } from '../../../../../../types'; import { SelectField } from '../../../../../shared/components/Form/SelectField'; -import { getBackupLocations } from '../../../../../shared/core/selectors'; +import { getBackupLocations, getBackupArtifacts } from '../../../../../shared/core/selectors'; import { Messages } from './Restore.messages'; import { RestoreService } from './Restore.service'; @@ -17,6 +18,8 @@ import { RestoreFields, RestoreFromProps } from './Restore.types'; export const Restore: FC = ({ form }) => { const styles = useStyles(getStyles); + const dispatch = useDispatch(); + const [enableRestore, setEnableRestore] = useState(false); const { result: locations = [], loading: locationsLoading } = useSelector(getBackupLocations); const locationsOptions = locations.map((location) => ({ @@ -24,8 +27,18 @@ export const Restore: FC = ({ form }) => { value: location.locationID, })); + const { result: backupArtifacts = [], loading: backupArtifactsLoading } = useSelector(getBackupArtifacts); + const { restoreFrom, kubernetesCluster } = form.getState().values; const restoreFromValue = restoreFrom?.value; + + useEffect(() => { + if (restoreFromValue && enableRestore) { + dispatch(fetchBackupArtifacts({ locationId: restoreFromValue })); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [restoreFromValue, enableRestore]); + return (
= ({ form }) => { )} {restoreFromValue !== undefined && restoreFromValue ? ( - RestoreService.loadBackupArtifacts(restoreFromValue)} - defaultOptions - placeholder={Messages.placeholders.backupArtifact} - label={Messages.labels.backupArtifact} - validate={validators.required} - /> + + {({ input }) => ( +
+ +
+ )} +
) : (
)} diff --git a/public/app/percona/shared/core/reducers/backups/backupArtifacts.ts b/public/app/percona/shared/core/reducers/backups/backupArtifacts.ts new file mode 100644 index 0000000000000..188845d6f623b --- /dev/null +++ b/public/app/percona/shared/core/reducers/backups/backupArtifacts.ts @@ -0,0 +1,23 @@ +import { createAsyncThunk } from '@reduxjs/toolkit'; + +import { SelectableValue } from '@grafana/data'; +import { createAsyncSlice, withSerializedError } from 'app/features/alerting/unified/utils/redux'; +import { DBaaSBackupService } from 'app/percona/dbaas/components/DBCluster/EditDBClusterPage/DBaaSBackups/DBaaSBackups.service'; +export const fetchBackupArtifacts = createAsyncThunk( + 'percona/fetchBackupArtifacts', + async (args: { locationId: string }, thunkAPI): Promise>> => + withSerializedError( + (async () => { + const backupArtifactsResponse = await DBaaSBackupService.list(args.locationId); + + return backupArtifactsResponse.map((backup) => ({ + label: backup.key, + value: backup.key, + })); + })() + ) +); + +const perconaBackupArtifactsSlice = createAsyncSlice('fetchBackupArtifacts', fetchBackupArtifacts, []).reducer; + +export default perconaBackupArtifactsSlice; diff --git a/public/app/percona/shared/core/reducers/index.ts b/public/app/percona/shared/core/reducers/index.ts index a2e54109edd3b..e61eef7691916 100644 --- a/public/app/percona/shared/core/reducers/index.ts +++ b/public/app/percona/shared/core/reducers/index.ts @@ -16,6 +16,7 @@ import { uiEventsReducer } from 'app/percona/ui-events/reducer'; import { ServerInfo } from '../types'; import advisorsReducers from './advisors/advisors'; +import perconaBackupArtifacts from './backups/backupArtifacts'; import perconaBackupLocations from './backups/backupLocations'; import perconaAddDBCluster from './dbaas/addDBCluster/addDBCluster'; import perconaDBClustersReducer from './dbaas/dbClusters/dbClusters'; @@ -248,6 +249,7 @@ export default { templates: templatesReducer, services: servicesReducer, nodes: nodesReducer, + backupArtifacts: perconaBackupArtifacts, backupLocations: perconaBackupLocations, tour: tourReducer, telemetry: uiEventsReducer, diff --git a/public/app/percona/shared/core/selectors.ts b/public/app/percona/shared/core/selectors.ts index 6434c64595103..9c84c01480e63 100644 --- a/public/app/percona/shared/core/selectors.ts +++ b/public/app/percona/shared/core/selectors.ts @@ -21,6 +21,7 @@ export const getTemplates = (state: StoreState) => state.percona.templates; export const getServices = (state: StoreState) => state.percona.services; export const getNodes = (state: StoreState) => state.percona.nodes; export const getBackupLocations = (state: StoreState) => state.percona.backupLocations; +export const getBackupArtifacts = (state: StoreState) => state.percona.backupArtifacts; export const getTour = (state: StoreState) => state.percona.tour; export const getAccessRoles = (state: StoreState) => state.percona.roles; export const getUsers = (state: StoreState) => state.users; diff --git a/public/app/percona/ui-events/components/Telemetry.tsx b/public/app/percona/ui-events/components/Telemetry.tsx index 77dee75bccf40..3ccc0f8bb2f2b 100644 --- a/public/app/percona/ui-events/components/Telemetry.tsx +++ b/public/app/percona/ui-events/components/Telemetry.tsx @@ -1,9 +1,9 @@ import React, { FC, useEffect } from 'react'; -import { useSelector } from 'react-redux'; import { getPerconaSettings } from 'app/percona/shared/core/selectors'; import { EventStore } from 'app/percona/ui-events/EventStore'; import { UIEventsService } from 'app/percona/ui-events/UIEvents.service'; +import { useSelector } from 'app/types'; export interface UiEventsProps {}