From d994a82760a8e26ed811774604630de046b4ef99 Mon Sep 17 00:00:00 2001 From: Rafael Agostini Date: Thu, 30 May 2024 16:20:07 -0500 Subject: [PATCH] Jetpack Backup: Update copy site flow to use the getRestoreProgress selector as restore status source of truth (#91145) * Update backup clone flow to use the getRestoreProgress status The progress bar is being updated according the getRestoreProgress() selector, so the idea is to consider the `status` value we get from there to validate if the restore is still in progress or it finished, instead of the `getInProgressRewindStatus` that might have some cache issues. * Update unit tests * Render QueryRewindRestoreStatus only on inProgress view * Update restoreId state only when it changes and user requests restore --- client/my-sites/backup/clone-flow/index.tsx | 49 ++++++++++++++----- .../my-sites/backup/clone-flow/test/index.jsx | 9 ++-- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/client/my-sites/backup/clone-flow/index.tsx b/client/my-sites/backup/clone-flow/index.tsx index 59a2840dcb27f..cb5166561282a 100644 --- a/client/my-sites/backup/clone-flow/index.tsx +++ b/client/my-sites/backup/clone-flow/index.tsx @@ -1,6 +1,6 @@ import { Button, Card, Gridicon } from '@automattic/components'; import { useTranslate } from 'i18n-calypso'; -import { FunctionComponent, useCallback, useState } from 'react'; +import { FunctionComponent, useCallback, useEffect, useState } from 'react'; import ActivityCardList from 'calypso/components/activity-card-list'; import AdvancedCredentials from 'calypso/components/advanced-credentials'; import DocumentHead from 'calypso/components/data/document-head'; @@ -27,7 +27,6 @@ import { getInProgressBackupForSite } from 'calypso/state/rewind/selectors'; import getBackupStagingSites from 'calypso/state/rewind/selectors/get-backup-staging-sites'; import hasFetchedStagingSitesList from 'calypso/state/rewind/selectors/has-fetched-staging-sites-list'; import isFetchingStagingSitesList from 'calypso/state/rewind/selectors/is-fetching-staging-sites-list'; -import getInProgressRewindStatus from 'calypso/state/selectors/get-in-progress-rewind-status'; import getJetpackCredentials from 'calypso/state/selectors/get-jetpack-credentials'; import getPreviousRoute from 'calypso/state/selectors/get-previous-route'; import getRestoreProgress from 'calypso/state/selectors/get-restore-progress'; @@ -77,6 +76,7 @@ const BackupCloneFlow: FunctionComponent< Props > = ( { siteId } ) => { const [ backupPeriod, setBackupPeriod ] = useState< string >( '' ); const [ backupDisplayDate, setBackupDisplayDate ] = useState< string >( '' ); const [ showCredentialForm, setShowCredentialForm ] = useState< boolean >( false ); + const [ restoreId, setRestoreId ] = useState< number | null >( null ); const activityLogPath = '/activity-log/' + siteSlug; const refreshBackups = useCallback( @@ -107,6 +107,32 @@ const BackupCloneFlow: FunctionComponent< Props > = ( { siteId } ) => { return getJetpackCredentials( state, siteId, cloneDestination ); } ); + useEffect( () => { + // Here we are updating the restoreId any time the user requests a new restore and only if the restoreId + // has changed to avoid unnecessary re-renders. + // This is necessary because the restoreId is used to query the restore progress in the + // QueryRewindRestoreStatus component. + if ( userHasRequestedRestore ) { + if ( isCloneToStaging && stagingSiteRewindState.rewind?.restoreId ) { + const newRestoreId = stagingSiteRewindState.rewind.restoreId; + if ( restoreId !== newRestoreId ) { + setRestoreId( newRestoreId ); + } + } else if ( ! isCloneToStaging && rewindState.rewind?.restoreId ) { + const newRestoreId = rewindState.rewind.restoreId; + if ( restoreId !== newRestoreId ) { + setRestoreId( newRestoreId ); + } + } + } + }, [ + isCloneToStaging, + rewindState, + stagingSiteRewindState, + restoreId, + userHasRequestedRestore, + ] ); + const getUrlFromCreds = () => { if ( ! cloneRoleCredentials ) { return ''; @@ -120,10 +146,12 @@ const BackupCloneFlow: FunctionComponent< Props > = ( { siteId } ) => { return ''; }; - const inProgressRewindStatus = useSelector( ( state ) => { - return getInProgressRewindStatus( state, restoreSiteId, backupPeriod ); - } ); - const { message, percent, currentEntry, status } = useSelector( ( state ) => { + const { + message, + percent, + currentEntry, + status: inProgressRewindStatus, + } = useSelector( ( state ) => { return getRestoreProgress( state, restoreSiteId ) || ( {} as RestoreProgress ); } ); @@ -245,11 +273,6 @@ const BackupCloneFlow: FunctionComponent< Props > = ( { siteId } ) => { const loading = rewindState.state === 'uninitialized'; - const restoreId = - ( isCloneToStaging - ? stagingSiteRewindState.rewind?.restoreId - : rewindState.rewind?.restoreId ) || null; - const disableClone = false; const { data: logs } = useRewindableActivityLogQuery( @@ -451,7 +474,7 @@ const BackupCloneFlow: FunctionComponent< Props > = ( { siteId } ) => { } ) } = ( { siteId } ) => { - { restoreId && 'running' === inProgressRewindStatus && ( + { restoreId && isInProgress && ( ) } { render() } diff --git a/client/my-sites/backup/clone-flow/test/index.jsx b/client/my-sites/backup/clone-flow/test/index.jsx index 829d32b2cf39f..2370430df69e9 100644 --- a/client/my-sites/backup/clone-flow/test/index.jsx +++ b/client/my-sites/backup/clone-flow/test/index.jsx @@ -6,7 +6,7 @@ import Modal from 'react-modal'; import useRewindableActivityLogQuery from 'calypso/data/activity-log/use-rewindable-activity-log-query'; import documentHead from 'calypso/state/document-head/reducer'; import preferences from 'calypso/state/preferences/reducer'; -import getInProgressRewindStatus from 'calypso/state/selectors/get-in-progress-rewind-status'; +import getRestoreProgress from 'calypso/state/selectors/get-restore-progress'; import getRewindState from 'calypso/state/selectors/get-rewind-state'; import ui from 'calypso/state/ui/reducer'; import { renderWithProvider } from 'calypso/test-helpers/testing-library'; @@ -71,8 +71,8 @@ jest.mock( 'calypso/state/rewind/selectors/get-backup-staging-sites', () => jest.mock( 'calypso/state/rewind/selectors/has-fetched-staging-sites-list' ); jest.mock( 'calypso/state/rewind/selectors/is-fetching-staging-sites-list' ); jest.mock( 'calypso/data/activity-log/use-rewindable-activity-log-query' ); -jest.mock( 'calypso/state/selectors/get-in-progress-rewind-status' ); jest.mock( 'calypso/state/selectors/get-rewind-state' ); +jest.mock( 'calypso/state/selectors/get-restore-progress' ); jest.mock( 'calypso/state/selectors/get-site-gmt-offset' ); jest.mock( 'calypso/state/selectors/get-site-timezone-value' ); jest.mock( 'calypso/state/selectors/get-jetpack-credentials-test-status' ); @@ -182,7 +182,6 @@ function progressThroughFlow() { describe( 'BackupCloneFlow render', () => { beforeEach( () => { jest.clearAllMocks(); - getInProgressRewindStatus.mockImplementation( () => undefined ); } ); test( 'Render RewindFlowLoading if state is not initialized', () => { @@ -216,7 +215,7 @@ describe( 'BackupCloneFlow render', () => { test( 'Render finished text if the clone is finished', () => { getRewindState.mockImplementation( () => ( { state: 'active' } ) ); - getInProgressRewindStatus.mockImplementation( () => 'finished' ); + getRestoreProgress.mockImplementation( () => ( { status: 'finished' } ) ); render( ); progressThroughFlow(); @@ -225,7 +224,7 @@ describe( 'BackupCloneFlow render', () => { test( 'Render error if it is in the wrong status', () => { getRewindState.mockImplementation( () => ( { state: 'active' } ) ); - getInProgressRewindStatus.mockImplementation( () => 'wrong-status' ); + getRestoreProgress.mockImplementation( () => ( { status: 'wrong-status' } ) ); render( ); progressThroughFlow();