Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add details to restore progress screen #47153

Merged
merged 9 commits into from
Nov 6, 2020
28 changes: 26 additions & 2 deletions client/my-sites/backup/rewind-flow/progress-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,40 @@ import React, { FunctionComponent } from 'react';
import { ProgressBar } from '@automattic/components';

interface Props {
isReady: boolean;
percent: number | null;
message?: string;
entry?: string;
}

const RewindFlowProgressBar: FunctionComponent< Props > = ( { percent } ) => {
const RewindFlowProgressBar: FunctionComponent< Props > = ( {
isReady,
percent,
message,
entry,
} ) => {
const translate = useTranslate();
const filteredPercent = percent !== null ? percent : 0;

return (
<div className="rewind-flow__progress-bar">
<p>{ translate( '%(filteredPercent)d%% complete', { args: { filteredPercent } } ) }</p>
<div className="rewind-flow__progress-bar-header">
<p className="rewind-flow__progress-bar-message">
{ isReady ? message : translate( 'Initializing the restore process' ) }
</p>
<p className="rewind-flow__progress-bar-percent">
{ translate( '%(filteredPercent)d%% complete', { args: { filteredPercent } } ) }
</p>
</div>
<ProgressBar value={ filteredPercent } total={ 100 } />
<p className="rewind-flow__progress-bar-entry">
{ isReady &&
entry &&
translate( 'Currently restoring: %s', {
args: entry,
comment: '%s entry is the file, table, etc. being restored',
} ) }
</p>
</div>
);
};
Expand Down
35 changes: 20 additions & 15 deletions client/my-sites/backup/rewind-flow/restore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { rewindRestore } from 'calypso/state/activity-log/actions';
import CheckYourEmail from './rewind-flow-notice/check-your-email';
import Error from './error';
import getInProgressRewindPercentComplete from 'calypso/state/selectors/get-in-progress-rewind-percent-complete';
import getInProgressRewindEntryDetails from 'calypso/state/selectors/get-in-progress-rewind-entry-details';
import getInProgressRewindStatus from 'calypso/state/selectors/get-in-progress-rewind-status';
import getRewindState from 'calypso/state/selectors/get-rewind-state';
import Gridicon from 'calypso/components/gridicon';
Expand All @@ -23,21 +24,18 @@ import QueryRewindState from 'calypso/components/data/query-rewind-state';
import RewindConfigEditor from './rewind-config-editor';
import RewindFlowNotice, { RewindFlowNoticeLevel } from './rewind-flow-notice';

/**
* Type dependencies
*/
import { RewindState } from 'calypso/state/data-layer/wpcom/sites/rewind/type';

interface Props {
backupDisplayDate: string;
rewindId: string;
siteId: number;
siteUrl: string;
}

//todo: move to dedicated types file
interface RewindState {
state: string;
rewind?: {
status: 'queued' | 'running' | 'finished' | 'fail';
};
}

const BackupRestoreFlow: FunctionComponent< Props > = ( {
backupDisplayDate,
rewindId,
Expand All @@ -51,25 +49,27 @@ const BackupRestoreFlow: FunctionComponent< Props > = ( {
const [ userHasRequestedRestore, setUserHasRequestedRestore ] = useState< boolean >( false );

const rewindState = useSelector( ( state ) => getRewindState( state, siteId ) ) as RewindState;

const loading = rewindState.state === 'uninitialized';

const inProgressRewindStatus = useSelector( ( state ) =>
getInProgressRewindStatus( state, siteId, rewindId )
);
const inProgressRewindPercentComplete = useSelector( ( state ) =>
getInProgressRewindPercentComplete( state, siteId, rewindId )
);
const inProgressRewindEntryDetails = useSelector( ( state ) =>
getInProgressRewindEntryDetails( state, siteId, rewindId )
);

const requestRestore = useCallback(
() => dispatch( rewindRestore( siteId, rewindId, rewindConfig ) ),
[ dispatch, rewindConfig, rewindId, siteId ]
);

const onConfirm = () => {
const onConfirm = useCallback( () => {
setUserHasRequestedRestore( true );
requestRestore();
};
}, [ setUserHasRequestedRestore, requestRestore ] );

const loading = rewindState.state === 'uninitialized';
const { message, currentEntry } = inProgressRewindEntryDetails;

const renderConfirm = () => (
<>
Expand Down Expand Up @@ -114,7 +114,12 @@ const BackupRestoreFlow: FunctionComponent< Props > = ( {
<Gridicon icon="history" size={ 48 } />
</div>
<h3 className="rewind-flow__title">{ translate( 'Currently restoring your site' ) }</h3>
<ProgressBar percent={ inProgressRewindPercentComplete } />
<ProgressBar
isReady={ 'running' === inProgressRewindStatus }
message={ message }
entry={ currentEntry }
percent={ inProgressRewindPercentComplete }
/>
<p className="rewind-flow__info">
{ translate(
'We are restoring your site back to {{strong}}%(backupDisplayDate)s{{/strong}}.',
Expand Down
21 changes: 19 additions & 2 deletions client/my-sites/backup/rewind-flow/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,29 @@ a.rewind-flow-notice__title-warning:visited {
margin-bottom: 22.5px;

p {
color: var( --color-neutral-light );
font-size: $font-body-extra-small;
font-size: $font-body-small;
margin: 0;
}
}

.rewind-flow__progress-bar-header {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}

.rewind-flow__progress-bar-percent {
color: var( --studio-gray-50 );
}

.rewind-flow__progress-bar-message {
font-weight: 700;
}

.rewind-flow__progress-bar-entry {
color: var( --studio-gray-50 );
}

.rewind-flow__info {
font-size: $font-body;
}
Expand Down
2 changes: 2 additions & 0 deletions client/state/data-layer/wpcom/sites/rewind/api-transformer.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ const transformRewind = ( data ) =>
startedAt: new Date( data.started_at ),
status: data.status,
},
data.message && { message: data.message },
data.current_entry && { currentEntry: data.current_entry },
data.progress && { progress: data.progress },
data.reason && { reason: data.reason },
data.links && data.links.dismiss && { dismiss: makeRewindDismisser( data.links.dismiss ) }
Expand Down
7 changes: 7 additions & 0 deletions client/state/data-layer/wpcom/sites/rewind/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ export const rewind = {
started_at: { type: 'string' },
progress: { type: 'integer' },
reason: { type: 'string' },
/**
* Commenting these out temporarily because API is returning a null value for current_entry,
* triggering a schema validation error. Once this is corrected on the backend (soon), we
* will activate these properties again.
**/
// message: { type: 'string' },
// current_entry: { type: 'string' },
},
required: [ 'restore_id', 'rewind_id', 'status' ],
};
Expand Down
7 changes: 7 additions & 0 deletions client/state/data-layer/wpcom/sites/rewind/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface RewindState {
state: string;
rewind?: {
status: 'queued' | 'running' | 'finished' | 'fail';
restoreId?: number;
};
}
33 changes: 33 additions & 0 deletions client/state/selectors/get-in-progress-rewind-entry-details.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* External dependencies
*/
import { pick } from 'lodash';

/**
* Internal dependencies
*/
import getRewindState from './get-rewind-state';

/**
* @typedef {Object} EntryDetails
* @property {string} message - The description of current action taking place
* @property {string} currentEntry - The value (filename/tablename) being processed
*/

/**
* Returns object containing rewind status current entry and message
*
* @param {object} globalState Global state tree
* @param {?number|string} siteId the site ID
* @param {string} rewindId the id of the rewind to get the rewind status entry and message
* @returns {EntryDetails} Details of the current rewind action
*/
export default function getInProgressRewindEntryDetails( globalState, siteId, rewindId ) {
const { state, rewind } = getRewindState( globalState, siteId );

if ( 'active' === state && rewind?.rewindId === rewindId ) {
return pick( rewind, [ 'message', 'currentEntry' ] );
}

return {};
}