summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components')
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/Admin.js247
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/Backups.js287
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/StatBlock.js19
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/admin-style.scss136
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/backups-style.scss180
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/backup-animation-1.svg33
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/backup-animation-2.svg33
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/backup-animation-3.svg42
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/cloud-alert.svg1
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/cloud.svg1
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/jetpack.svg1
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/plugins.svg1
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/posts.svg1
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/themes.svg1
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/uploads.svg1
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/masthead/calypso-colors.scss60
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/masthead/calypso-mixins.scss351
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/masthead/masthead-style.scss89
-rw-r--r--plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/stat-block-style.scss46
19 files changed, 1530 insertions, 0 deletions
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/Admin.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/Admin.js
new file mode 100644
index 00000000..9f90d5d7
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/Admin.js
@@ -0,0 +1,247 @@
+/**
+ * External dependencies
+ */
+import { useState, useEffect } from '@wordpress/element';
+import { __ } from '@wordpress/i18n';
+import apiFetch from '@wordpress/api-fetch';
+import { useSelect } from '@wordpress/data';
+import {
+ AdminPage,
+ AdminSection,
+ AdminSectionHero,
+ Container,
+ Col,
+ getRedirectUrl,
+ PricingCard,
+} from '@automattic/jetpack-components';
+
+/**
+ * Internal dependencies
+ */
+import Backups from './Backups';
+import useConnection from '../hooks/useConnection';
+import './admin-style.scss';
+import './masthead/masthead-style.scss';
+import { STORE_ID } from '../store';
+
+/* eslint react/react-in-jsx-scope: 0 */
+const Admin = () => {
+ const [ connectionStatus, renderConnectScreen ] = useConnection();
+ const [ capabilities, setCapabilities ] = useState( [] );
+ const [ capabilitiesError, setCapabilitiesError ] = useState( null );
+ const [ connectionLoaded, setConnectionLoaded ] = useState( false );
+ const [ capabilitiesLoaded, setCapabilitiesLoaded ] = useState( false );
+ const [ showHeaderFooter, setShowHeaderFooter ] = useState( true );
+ const [ price, setPrice ] = useState( 0 );
+ const [ priceAfter, setPriceAfter ] = useState( 0 );
+
+ const domain = useSelect( select => select( STORE_ID ).getCalypsoSlug(), [] );
+
+ useEffect( () => {
+ if ( 0 < Object.keys( connectionStatus ).length ) {
+ setConnectionLoaded( true );
+ }
+ }, [ connectionStatus ] );
+
+ useEffect( () => {
+ apiFetch( { path: '/jetpack/v4/backup-capabilities' } ).then(
+ res => {
+ setCapabilities( res.capabilities );
+ setCapabilitiesLoaded( true );
+ },
+ () => {
+ setCapabilitiesLoaded( true );
+ setCapabilitiesError( 'Failed to fetch site capabilities' );
+ }
+ );
+ apiFetch( { path: '/jetpack/v4/backup-promoted-product-info' } ).then( res => {
+ setPrice( res.cost / 12 );
+ if ( res.introductory_offer ) {
+ setPriceAfter( res.introductory_offer.cost_per_interval / 12 );
+ } else {
+ setPriceAfter( res.cost / 12 );
+ }
+ } );
+ }, [] );
+
+ const isFullyConnected = () => {
+ return connectionLoaded && connectionStatus.isUserConnected && connectionStatus.isRegistered;
+ };
+
+ const hasBackupPlan = () => {
+ return capabilities.includes( 'backup' );
+ };
+
+ const sendToCart = () => {
+ window.location.href = getRedirectUrl( 'backup-plugin-upgrade-10gb', { site: domain } );
+ };
+
+ const renderNoBackupCapabilities = () => {
+ const basicInfoText = __( '14 day money back guarantee.', 'jetpack-backup-pkg' );
+ const introductoryInfoText = __(
+ 'Special introductory pricing, all renewals are at full price. 14 day money back guarantee.',
+ 'jetpack-backup-pkg'
+ );
+ return (
+ <Container horizontalSpacing={ 3 } horizontalGap={ 3 }>
+ <Col lg={ 6 } md={ 6 } sm={ 4 }>
+ <h1>{ __( 'Secure your site with a Backup subscription.', 'jetpack-backup-pkg' ) }</h1>
+ <p>
+ { ' ' }
+ { __(
+ 'Get peace of mind knowing that all your work will be saved, and get back online quickly with one-click restores.',
+ 'jetpack-backup-pkg'
+ ) }
+ </p>
+ <ul className="jp-product-promote">
+ <li>{ __( 'Automated real-time backups', 'jetpack-backup-pkg' ) }</li>
+ <li>{ __( 'Easy one-click restores', 'jetpack-backup-pkg' ) }</li>
+ <li>{ __( 'Complete list of all site changes', 'jetpack-backup-pkg' ) }</li>
+ <li>{ __( 'Global server infrastructure', 'jetpack-backup-pkg' ) }</li>
+ <li>{ __( 'Best-in-class support', 'jetpack-backup-pkg' ) }</li>
+ </ul>
+ </Col>
+ <Col lg={ 1 } md={ 1 } sm={ 0 } />
+ <Col lg={ 5 } md={ 6 } sm={ 4 }>
+ <PricingCard
+ ctaText={ __( 'Get Jetpack Backup', 'jetpack-backup-pkg' ) }
+ icon="data:image/svg+xml,%3Csvg width='32' height='32' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='m21.092 15.164.019-1.703v-.039c0-1.975-1.803-3.866-4.4-3.866-2.17 0-3.828 1.351-4.274 2.943l-.426 1.524-1.581-.065a2.92 2.92 0 0 0-.12-.002c-1.586 0-2.977 1.344-2.977 3.133 0 1.787 1.388 3.13 2.973 3.133H22.399c1.194 0 2.267-1.016 2.267-2.4 0-1.235-.865-2.19-1.897-2.368l-1.677-.29Zm-10.58-3.204a4.944 4.944 0 0 0-.201-.004c-2.75 0-4.978 2.298-4.978 5.133s2.229 5.133 4.978 5.133h12.088c2.357 0 4.267-1.97 4.267-4.4 0-2.18-1.538-3.99-3.556-4.339v-.06c0-3.24-2.865-5.867-6.4-5.867-2.983 0-5.49 1.871-6.199 4.404Z' fill='%23000'/%3E%3C/svg%3E"
+ infoText={ priceAfter === price ? basicInfoText : introductoryInfoText }
+ // eslint-disable-next-line react/jsx-no-bind
+ onCtaClick={ sendToCart }
+ priceAfter={ priceAfter }
+ priceBefore={ price }
+ title={ __( 'Jetpack Backup', 'jetpack-backup-pkg' ) }
+ />
+ </Col>
+ </Container>
+ );
+ };
+
+ const renderLoadedState = () => {
+ if (
+ ! connectionLoaded ||
+ ! connectionStatus.isUserConnected ||
+ ! connectionStatus.isRegistered
+ ) {
+ if ( showHeaderFooter ) {
+ setShowHeaderFooter( false );
+ }
+
+ return (
+ <Container horizontalSpacing={ 3 } horizontalGap={ 3 }>
+ <Col lg={ 12 } md={ 8 } sm={ 4 }>
+ { renderConnectScreen() }
+ </Col>
+ </Container>
+ );
+ }
+
+ // Show header and footer on all screens except ConnectScreen
+ if ( ! showHeaderFooter ) {
+ setShowHeaderFooter( true );
+ }
+
+ if ( ! capabilitiesLoaded ) {
+ return <div></div>;
+ }
+
+ if ( hasBackupPlan() ) {
+ return (
+ <Container horizontalSpacing={ 5 } fluid>
+ <Col>
+ <Backups />
+ </Col>
+ </Container>
+ );
+ }
+
+ // Render an error state, this shouldn't occurr since we've passed userConnected checks
+ if ( capabilitiesError ) {
+ return (
+ <Container horizontalSpacing={ 3 }>
+ <Col lg={ 12 } md={ 8 } sm={ 4 }>
+ { capabilitiesError }
+ </Col>
+ </Container>
+ );
+ }
+
+ return renderNoBackupCapabilities();
+ };
+
+ // Renders additional segments under the jp-hero area condition on having a backup plan
+ const renderBackupSegments = () => {
+ return (
+ <Container horizontalSpacing={ 3 } horizontalGap={ 3 }>
+ <Col lg={ 6 } md={ 4 }>
+ <h2>{ __( 'Your cloud backups', 'jetpack-backup-pkg' ) }</h2>
+ <p>
+ { __(
+ 'All the backups are safely stored in the cloud and available for you at any time on Jetpack.com, with full details about status and content.',
+ 'jetpack-backup-pkg'
+ ) }
+ </p>
+ { hasBackupPlan() && (
+ <>
+ <p>
+ <a
+ href={ getRedirectUrl( 'jetpack-backup', { site: domain } ) }
+ target="_blank"
+ rel="noreferrer"
+ >
+ { __( 'See all your backups', 'jetpack-backup-pkg' ) }
+ </a>
+ </p>
+ </>
+ ) }
+ </Col>
+ <Col lg={ 1 } md={ 1 } sm={ 0 } />
+ <Col lg={ 5 } md={ 3 } sm={ 4 }>
+ <h2>{ __( "Your site's heartbeat", 'jetpack-backup-pkg' ) }</h2>
+ <p>
+ { __(
+ 'The activity log lets you see everything that’s going on with your site outlined in an organized, readable way.',
+ 'jetpack-backup-pkg'
+ ) }
+ </p>
+ { hasBackupPlan() && (
+ <p>
+ <a
+ href={ getRedirectUrl( 'backup-plugin-activity-log', { site: domain } ) }
+ target="_blank"
+ rel="noreferrer"
+ >
+ { __( "See your site's activity", 'jetpack-backup-pkg' ) }
+ </a>
+ </p>
+ ) }
+ </Col>
+ </Container>
+ );
+ };
+
+ const renderContent = () => {
+ return (
+ <div className="content">
+ <AdminSectionHero>{ renderLoadedState() }</AdminSectionHero>
+ <AdminSection>{ isFullyConnected() && renderBackupSegments() }</AdminSection>
+ </div>
+ );
+ };
+
+ return (
+ <AdminPage
+ withHeader={ showHeaderFooter }
+ withFooter={ showHeaderFooter }
+ moduleName={ __( 'Jetpack Backup', 'jetpack-backup-pkg' ) }
+ a8cLogoHref="https://www.jetpack.com"
+ >
+ <div id="jetpack-backup-admin-container" className="jp-content">
+ { renderContent() }
+ </div>
+ </AdminPage>
+ );
+};
+
+export default Admin;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/Backups.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/Backups.js
new file mode 100644
index 00000000..ed02e77f
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/Backups.js
@@ -0,0 +1,287 @@
+/**
+ * External dependencies
+ */
+import { getDate, date, dateI18n } from '@wordpress/date';
+import { __, sprintf } from '@wordpress/i18n';
+import apiFetch from '@wordpress/api-fetch';
+import { createInterpolateElement, useState, useEffect } from '@wordpress/element';
+import { useSelect } from '@wordpress/data';
+import { getRedirectUrl } from '@automattic/jetpack-components';
+
+/**
+ * Internal dependencies
+ */
+import { STORE_ID } from '../store';
+import StatBlock from './StatBlock';
+import './backups-style.scss';
+import PostsIcon from './icons/posts.svg';
+import CloudIcon from './icons/cloud.svg';
+import CloudAlertIcon from './icons/cloud-alert.svg';
+import UploadsIcon from './icons/uploads.svg';
+import PluginsIcon from './icons/plugins.svg';
+import ThemesIcon from './icons/themes.svg';
+import BackupAnim1 from './icons/backup-animation-1.svg';
+import BackupAnim2 from './icons/backup-animation-2.svg';
+import BackupAnim3 from './icons/backup-animation-3.svg';
+
+/* eslint react/react-in-jsx-scope: 0 */
+const Backups = () => {
+ // State information
+ const [ progress, setProgress ] = useState( 0 );
+ const [ trackProgress, setTrackProgress ] = useState( 0 );
+ const [ latestTime, setLatestTime ] = useState( '' );
+ const [ stats, setStats ] = useState( {
+ posts: 0,
+ uploads: 0,
+ plugins: 0,
+ themes: 0,
+ } );
+ const domain = useSelect( select => select( STORE_ID ).getCalypsoSlug(), [] );
+ const siteTitle = useSelect( select => select( STORE_ID ).getSiteTitle(), '' );
+
+ const BACKUP_STATE = {
+ LOADING: 0,
+ IN_PROGRESS: 1,
+ NO_BACKUPS: 2,
+ NO_BACKUPS_RETRY: 3,
+ NO_GOOD_BACKUPS: 4,
+ COMPLETE: 5,
+ };
+ const [ backupState, setBackupState ] = useState( BACKUP_STATE.LOADING );
+
+ const progressInterval = 1 * 1000; // How often to poll for backup progress updates.
+
+ // Loads data on startup and whenever trackProgress updates.
+ useEffect( () => {
+ apiFetch( { path: '/jetpack/v4/backups' } ).then(
+ res => {
+ // If we have no backups don't load up stats.
+ let latestBackup = null;
+ if ( res.length === 0 ) {
+ setBackupState( BACKUP_STATE.NO_BACKUPS );
+ } else if ( res.length === 1 && 'error-will-retry' === res[ 0 ].status ) {
+ setBackupState( BACKUP_STATE.NO_BACKUPS_RETRY );
+ } else {
+ // Check for the first completed backups.
+ res.forEach( backup => {
+ if ( null !== latestBackup ) {
+ return;
+ }
+
+ if ( 'finished' === backup.status && backup.stats ) {
+ latestBackup = backup;
+ setBackupState( BACKUP_STATE.COMPLETE );
+ }
+ } );
+
+ // Only the first backup can be in progress.
+ if ( null === latestBackup && 'started' === res[ 0 ].status ) {
+ latestBackup = res[ 0 ];
+ setProgress( latestBackup.percent );
+ setBackupState( BACKUP_STATE.IN_PROGRESS );
+ }
+
+ // No complete or in progress backups.
+ if ( ! latestBackup ) {
+ setBackupState( BACKUP_STATE.NO_GOOD_BACKUPS );
+ return;
+ }
+
+ // Setup data for COMPLETE state.
+ if ( 'finished' === latestBackup.status ) {
+ const postsTable = latestBackup.stats.prefix + 'posts';
+ setStats( {
+ plugins: latestBackup.stats.plugins.count,
+ themes: latestBackup.stats.themes.count,
+ uploads: latestBackup.stats.uploads.count,
+ posts: latestBackup.stats.tables[ postsTable ].post_published,
+ } );
+ setLatestTime( date( 'c', latestBackup.last_updated + '+00:00' ) );
+ }
+ }
+
+ // Repeat query for NO_BACKUPS (before first) and IN_PROGRESS
+ if ( res.length === 0 || 'started' === latestBackup.status ) {
+ // Grab progress and update every progressInterval until complete.
+ setTimeout( () => {
+ setTrackProgress( trackProgress + 1 );
+ }, progressInterval );
+ }
+ },
+ () => {
+ setBackupState( BACKUP_STATE.NO_GOOD_BACKUPS );
+ }
+ );
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [ trackProgress ] );
+
+ const renderInProgressBackup = ( showProgressBar = true ) => {
+ return (
+ <div className="jp-row">
+ <div className="lg-col-span-5 md-col-span-8 sm-col-span-4">
+ { showProgressBar && (
+ <div className="backup__progress">
+ <div className="backup__progress-info">
+ <p>
+ { sprintf(
+ /* translators: placeholder is the Site Title */
+ __( 'Backing up %s', 'jetpack-backup-pkg' ),
+ siteTitle
+ ) }
+ </p>
+ <p className="backup__progress-info-percentage">{ progress }%</p>
+ </div>
+ <div className="backup__progress-bar">
+ <div
+ className="backup__progress-bar-actual"
+ style={ { width: progress + '%' } }
+ ></div>
+ </div>
+ </div>
+ ) }
+ <h1>{ __( 'Your first cloud backup will be ready soon', 'jetpack-backup-pkg' ) }</h1>
+ <p>
+ { __(
+ 'The first backup usually takes a few minutes, so it will become available soon.',
+ 'jetpack-backup-pkg'
+ ) }
+ </p>
+ <p>
+ { createInterpolateElement(
+ __(
+ 'In the meanwhile, you can start getting familiar with your <a>backup management on Jetpack.com</a>.',
+ 'jetpack-backup-pkg'
+ ),
+ {
+ a: (
+ <a
+ href={ getRedirectUrl( 'jetpack-backup', { site: domain } ) }
+ target="_blank"
+ rel="noreferrer"
+ />
+ ),
+ }
+ ) }
+ </p>
+ </div>
+ <div className="lg-col-span-1 md-col-span-4 sm-col-span-0"></div>
+ <div className="backup__animation lg-col-span-6 md-col-span-2 sm-col-span-2">
+ <img className="backup__animation-el-1" src={ BackupAnim1 } alt="" />
+ <img className="backup__animation-el-2" src={ BackupAnim2 } alt="" />
+ <img className="backup__animation-el-3" src={ BackupAnim3 } alt="" />
+ </div>
+ </div>
+ );
+ };
+
+ const formatDateString = dateString => {
+ const todayString = __( 'Today', 'jetpack-backup-pkg' );
+ const todayDate = getDate();
+ let backupDate = todayString;
+ if ( dateI18n( 'zY', todayDate ) !== dateI18n( 'zY', dateString ) ) {
+ backupDate = dateI18n( 'M j', dateString );
+ }
+ const backupTime = dateI18n( 'g:i A', dateString );
+
+ return backupDate + ', ' + backupTime;
+ };
+
+ const renderCompleteBackup = () => {
+ return (
+ <div className="jp-row">
+ <div className="lg-col-span-3 md-col-span-4 sm-col-span-4">
+ <div className="backup__latest">
+ <img src={ CloudIcon } alt="" />
+ <h2>{ __( 'Latest Backup', 'jetpack-backup-pkg' ) }</h2>
+ </div>
+ <h1>{ formatDateString( latestTime ) }</h1>
+ <a
+ className="button is-full-width"
+ href={ getRedirectUrl( 'jetpack-backup', { site: domain } ) }
+ target="_blank"
+ rel="noreferrer"
+ >
+ { __( 'See all your backups', 'jetpack-backup-pkg' ) }
+ </a>
+ </div>
+ <div className="lg-col-span-1 md-col-span-4 sm-col-span-0"></div>
+ <div className="lg-col-span-2 md-col-span-2 sm-col-span-2">
+ <StatBlock
+ icon={ PostsIcon }
+ label={ __( 'Posts', 'jetpack-backup-pkg' ) }
+ value={ stats.posts }
+ />
+ </div>
+ <div className="lg-col-span-2 md-col-span-2 sm-col-span-2">
+ <StatBlock
+ icon={ UploadsIcon }
+ label={ __( 'Uploads', 'jetpack-backup-pkg' ) }
+ value={ stats.uploads }
+ />
+ </div>
+ <div className="lg-col-span-2 md-col-span-2 sm-col-span-2">
+ <StatBlock
+ icon={ PluginsIcon }
+ label={ __( 'Plugins', 'jetpack-backup-pkg' ) }
+ value={ stats.plugins }
+ />
+ </div>
+ <div className="lg-col-span-2 md-col-span-2 sm-col-span-2">
+ <StatBlock
+ icon={ ThemesIcon }
+ label={ __( 'Themes', 'jetpack-backup-pkg' ) }
+ value={ stats.themes }
+ />
+ </div>
+ </div>
+ );
+ };
+
+ const renderNoGoodBackups = () => {
+ return (
+ <div className="jp-row">
+ <div className="lg-col-span-5 md-col-span-4 sm-col-span-4">
+ <img src={ CloudAlertIcon } alt="" />
+ <h1>{ __( "We're having trouble backing up your site", 'jetpack-backup-pkg' ) }</h1>
+ <p>
+ { createInterpolateElement(
+ __(
+ ' <a>Get in touch with us</a> to get your site backups going again.',
+ 'jetpack-backup-pkg'
+ ),
+ {
+ a: (
+ <a
+ //TODO: we may want to add a specific redirect for Backup plugin related issues
+ href={ getRedirectUrl( 'jetpack-contact-support', { site: domain } ) }
+ target="_blank"
+ rel="noreferrer"
+ />
+ ),
+ }
+ ) }
+ </p>
+ </div>
+ <div className="lg-col-span-1 md-col-span-4 sm-col-span-0"></div>
+ <div className="lg-col-span-6 md-col-span-2 sm-col-span-2"></div>
+ </div>
+ );
+ };
+
+ const renderLoading = () => {
+ return <div className="jp-row"></div>;
+ };
+
+ return (
+ <div className="jp-wrap jp-content">
+ { BACKUP_STATE.LOADING === backupState && renderLoading() }
+ { BACKUP_STATE.NO_BACKUPS === backupState && renderInProgressBackup() }
+ { BACKUP_STATE.NO_BACKUPS_RETRY === backupState && renderInProgressBackup( false ) }
+ { BACKUP_STATE.IN_PROGRESS === backupState && renderInProgressBackup() }
+ { BACKUP_STATE.COMPLETE === backupState && renderCompleteBackup() }
+ { BACKUP_STATE.NO_GOOD_BACKUPS === backupState && renderNoGoodBackups() }
+ </div>
+ );
+};
+
+export default Backups;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/StatBlock.js b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/StatBlock.js
new file mode 100644
index 00000000..c19b3ae8
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/StatBlock.js
@@ -0,0 +1,19 @@
+/**
+ * Internal dependencies
+ */
+import './stat-block-style.scss';
+
+/* eslint react/react-in-jsx-scope: 0 */
+const StatBlock = props => {
+ return (
+ <div className="backup__card">
+ <img src={ props.icon } alt="" />
+ <div className="backup__card-details">
+ <div className="backup__card-details-items">{ props.label }</div>
+ <div className="backup__card-details-amount">{ props.value }</div>
+ </div>
+ </div>
+ );
+};
+
+export default StatBlock;
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/admin-style.scss b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/admin-style.scss
new file mode 100644
index 00000000..4141bcf9
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/admin-style.scss
@@ -0,0 +1,136 @@
+@import '@automattic/jetpack-base-styles/style';
+
+.jp-header,
+.jp-footer {
+ padding: 20px 0;
+
+ @include for-tablet-up {
+ padding: 40px 0;
+ }
+}
+
+.jp-content {
+ position: relative;
+ font-size: var( --font-body );
+ line-height: 1.5;
+
+ h1, h2, h3, h4, h5, h6 {
+ margin-top: 0;
+ line-height: 1.2;
+ }
+
+ h1 {
+ font-size: var( --font-title-large );
+ font-weight: 600;
+ }
+
+ h2 {
+ font-size: var( --font-title-small );
+ font-weight: 500;
+ }
+
+ .jp-section {
+ h2, h3 {
+ margin-bottom: 16px;
+ }
+
+ p {
+ margin-top: 16px;
+ }
+ }
+
+ p, li {
+ font-size: 16px;
+ line-height: 1.5;
+ }
+
+ .jp-connection-status-card h3, .jpb-my-plan-container h3 {
+ margin-top: 48px;
+ font-size: var( --font-title-small );
+ font-weight: 500;
+ }
+
+ a {
+ color: var( --jp-black );
+ transition: color, background-color 0.15s ease-out;
+
+ &:hover {
+ text-decoration-thickness: var( --jp-underline-thickness );
+ }
+
+ &:focus {
+ outline-color: var( --jp-black );
+ }
+ }
+
+ .button {
+ display: inline-block;
+ padding: 8px 24px;
+ font-weight: 500;
+ color: var( --jp-white );
+ background: var( --jp-black );
+ text-decoration: none;
+ border-radius: var( --jp-border-radius );
+ border: 0;
+ border-color: var( --jp-black );
+
+ &.is-full-width {
+ width: 100%;
+ text-align: center;
+ }
+
+ &:hover,
+ &:active {
+ background: var( --jp-black-80 );
+ color: var( --jp-white );
+ }
+
+ &:focus {
+ box-shadow: 0 0 0 1px var( --jp-white ) inset, 0 0 0 2px var( --jp-black );
+ }
+
+ &:disabled,
+ &.disabled {
+ background: var( --jp-gray );
+ pointer-events: none;
+ }
+ }
+
+ ul.jp-product-promote li {
+ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAANlBMVEVHcEwFnwUInggGnggGnggHnAcAnwUFnQcAnwcGnwkFnQgGnQgFnwcGnQYFnQcFnAcGnQkDnwdhiL0pAAAAEnRSTlMAMF//f2Aw7yBQ3+9gcIBgcED+HDbkAAAAZklEQVR4Ae3LNwICARDDQC0+cv7/Y8mwV9odSfWIcf/+VegnGkIvDaGXKvTTn/Gz+Uf5xTL0K1XotS7fs5H6GHvvaO8d7c3j7rdgHne/A/PYt/cO+R42oYdN6OEQetiFHo4A//6dAXqtBEkmtWutAAAAAElFTkSuQmCC) no-repeat;
+ background-size: 24px;
+ padding-left: 30px;
+ margin-bottom: 9px;
+ color: var(--jp-black);
+ }
+}
+
+.jp-hero {
+ margin-bottom: 64px;
+ padding: 64px 0;
+ background: var( --jp-white-off );
+
+ &.is-backup-performing {
+ background-image: url("data:image/svg+xml,%3Csvg width='624' height='400' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M624 88.387C575.321 34.082 504.674 0 426 0 323.405 0 234.3 58.22 189.925 143.42 83.07 154.78 0 245.305 0 355c0 38.16 10.072 73.999 27.698 105H624V88.387z' fill='%23fff'/%3E%3C/svg%3E");
+ background-position: 100% 100%;
+ background-repeat: no-repeat;
+ }
+
+ &.is-backup-healthy,
+ &.is-backup-error {
+ display: none;
+ }
+
+ p + .button {
+ margin-top: 18px;
+ }
+}
+
+.jp-dashboard-footer {
+ padding: 40px 0;
+}
+
+.jp-connection-status-card--status {
+ margin: 30px 0;
+}
+
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/backups-style.scss b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/backups-style.scss
new file mode 100644
index 00000000..5d0850a1
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/backups-style.scss
@@ -0,0 +1,180 @@
+@import '@automattic/jetpack-base-styles/style';
+@import 'masthead/calypso-mixins';
+
+.backup__card {
+ padding: 24px;
+ background: var( --jp-white );
+ box-shadow: 0px 0px 40px rgba( 0, 0, 0, 0.08 );
+ border-radius: var( --jp-border-radius );
+}
+
+.backup__card-details-items {
+ margin: 16px 0 -8px;
+ font-weight: 500;
+}
+
+.backup__card-details-amount {
+ margin-bottom: -12px;
+ font-size: var( --font-title-large );
+ font-weight: 600;
+}
+
+.backup__progress {
+ margin-right: 64px;
+ margin-bottom: 48px;
+}
+
+.backup__progress-info {
+ display: flex;
+ font-weight: 500;
+
+ .backup__progress-info-percentage {
+ margin-left: auto;
+ }
+}
+
+.backup__progress-bar,
+.backup__progress-bar-actual {
+ height: 12px;
+ border-radius: 8px;
+}
+
+.backup__progress-bar {
+ position: relative;
+ width: 100%;
+ background: var( --jp-gray-off );
+}
+
+.backup__progress-bar-actual {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 0%;
+ background: var( --jp-green-primary );
+}
+.backup__latest {
+ display: flex;
+ align-items: center;
+ margin-bottom: 8px;
+
+ svg,
+ img {
+ min-width: 32px;
+ min-height: 32px;
+ }
+
+ h2 {
+ margin: 0;
+ margin-left: 12px;
+ vertical-align: -1px;
+ }
+
+ + h1 {
+ white-space: nowrap;
+ }
+}
+
+.backup__animation {
+ position: relative;
+
+ @include responsive( full-width ) {
+ display: none;
+ }
+}
+
+.backup__animation-el-1,
+.backup__animation-el-2,
+.backup__animation-el-3 {
+ opacity: 0;
+ position: absolute;
+ z-index: 4;
+ animation: animation-el-3 4s ease-in-out 0.8s infinite normal forwards;
+}
+
+.backup__animation-el-1 {
+ bottom: 150px;
+ right: 264px;
+ animation-name: animation-el-1;
+ animation-delay: 0.6s;
+}
+
+.backup__animation-el-2 {
+ bottom: 108px;
+ right: 44px;
+ animation-name: animation-el-2;
+ animation-delay: 0.7s;
+}
+
+.backup__animation-el-3 {
+ bottom: -32px;
+ animation-name: animation-el-3;
+}
+
+@keyframes animation-el-1 {
+ 0% {
+ opacity: 0;
+ transform: translateY( 32px );
+ }
+ 20% {
+ opacity: 1;
+ transform: translateY( 0 );
+ }
+ 50% {
+ opacity: 1;
+ transform: translateY( 0 );
+ }
+ 60% {
+ opacity: 0;
+ transform: translateY( -96px );
+ }
+ 100% {
+ opacity: 0;
+ transform: translateY( -96px );
+ }
+}
+
+@keyframes animation-el-2 {
+ 0% {
+ opacity: 0;
+ transform: translateY( 64px );
+ }
+ 20% {
+ opacity: 1;
+ transform: translateY( 0 );
+ }
+ 50% {
+ opacity: 1;
+ transform: translateY( 0 );
+ }
+ 60% {
+ opacity: 0;
+ transform: translateY( -96px );
+ }
+ 100% {
+ opacity: 0;
+ transform: translateY( -96px );
+ }
+}
+
+@keyframes animation-el-3 {
+ 0% {
+ opacity: 0;
+ transform: translateY( 44px );
+ }
+ 20% {
+ opacity: 1;
+ transform: translateY( 0 );
+ }
+ 50% {
+ opacity: 1;
+ transform: translateY( 0 );
+ }
+ 60% {
+ opacity: 0;
+ transform: translateY( -84px );
+ }
+ 100% {
+ opacity: 0;
+ transform: translateY( -84px );
+ }
+}
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/backup-animation-1.svg b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/backup-animation-1.svg
new file mode 100644
index 00000000..08c42d96
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/backup-animation-1.svg
@@ -0,0 +1,33 @@
+<svg
+ class="backup__animation-el-1"
+ width="176"
+ height="212"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+>
+ <g filter="url(#filter1_d)">
+ <rect x="40" y="40" width="96" height="132" rx="3" fill="#98C6D9"></rect>
+ </g>
+ <defs>
+ <filter
+ id="filter1_d"
+ x="0"
+ y="0"
+ width="176"
+ height="212"
+ filterUnits="userSpaceOnUse"
+ color-interpolation-filters="sRGB"
+ >
+ <feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood>
+ <feColorMatrix
+ in="SourceAlpha"
+ values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
+ ></feColorMatrix>
+ <feOffset></feOffset>
+ <feGaussianBlur stdDeviation="20"></feGaussianBlur>
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0"></feColorMatrix>
+ <feBlend in2="BackgroundImageFix" result="effect1_dropShadow"></feBlend>
+ <feBlend in="SourceGraphic" in2="effect1_dropShadow" result="shape"></feBlend>
+ </filter>
+ </defs>
+</svg> \ No newline at end of file
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/backup-animation-2.svg b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/backup-animation-2.svg
new file mode 100644
index 00000000..414816b6
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/backup-animation-2.svg
@@ -0,0 +1,33 @@
+<svg
+ class="backup__animation-el-2"
+ width="248"
+ height="200"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+>
+ <g filter="url(#filter2_d)">
+ <rect x="40" y="40" width="168" height="120" rx="3" fill="#F2D76B"></rect>
+ </g>
+ <defs>
+ <filter
+ id="filter2_d"
+ x="0"
+ y="0"
+ width="248"
+ height="200"
+ filterUnits="userSpaceOnUse"
+ color-interpolation-filters="sRGB"
+ >
+ <feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood>
+ <feColorMatrix
+ in="SourceAlpha"
+ values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
+ ></feColorMatrix>
+ <feOffset></feOffset>
+ <feGaussianBlur stdDeviation="20"></feGaussianBlur>
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0"></feColorMatrix>
+ <feBlend in2="BackgroundImageFix" result="effect2_dropShadow"></feBlend>
+ <feBlend in="SourceGraphic" in2="effect2_dropShadow" result="shape"></feBlend>
+ </filter>
+ </defs>
+</svg>
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/backup-animation-3.svg b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/backup-animation-3.svg
new file mode 100644
index 00000000..eb3ff3a2
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/backup-animation-3.svg
@@ -0,0 +1,42 @@
+<svg
+ class="backup__animation-el-3"
+ width="536"
+ height="196"
+ fill="none"
+ xmlns="http://www.w3.org/2000/svg"
+>
+ <g filter="url(#filter3_d)">
+ <rect x="40" y="40" width="456" height="116" rx="8" fill="#fff"></rect>
+ </g>
+ <path
+ d="M475.35 62.04A7.49 7.49 0 00468 56c-2.89 0-5.4 1.64-6.65 4.04A5.994 5.994 0 00456 66c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z"
+ fill="#E9EFF5"
+ ></path>
+ <circle cx="100" cy="98" r="36" fill="#F7A8C3"></circle>
+ <path
+ d="M160 84a6 6 0 016-6h174a6 6 0 110 12H166a6 6 0 01-6-6zM160 112a6 6 0 016-6h276a6 6 0 110 12H166a6 6 0 01-6-6z"
+ fill="#E9EFF5"
+ ></path>
+ <defs>
+ <filter
+ id="filter3_d"
+ x="0"
+ y="0"
+ width="536"
+ height="196"
+ filterUnits="userSpaceOnUse"
+ color-interpolation-filters="sRGB"
+ >
+ <feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood>
+ <feColorMatrix
+ in="SourceAlpha"
+ values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
+ ></feColorMatrix>
+ <feOffset></feOffset>
+ <feGaussianBlur stdDeviation="20"></feGaussianBlur>
+ <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0"></feColorMatrix>
+ <feBlend in2="BackgroundImageFix" result="effect3_dropShadow"></feBlend>
+ <feBlend in="SourceGraphic" in2="effect3_dropShadow" result="shape"></feBlend>
+ </filter>
+ </defs>
+</svg> \ No newline at end of file
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/cloud-alert.svg b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/cloud-alert.svg
new file mode 100644
index 00000000..9440bdd0
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/cloud-alert.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="32" height="32" viewBox="0 0 24 24"><path fill="#d63639" d="M19 20H6C2.7 20 0 17.3 0 14C0 10.9 2.3 8.4 5.3 8C6.6 5.6 9.1 4 12 4C15.6 4 18.7 6.6 19.4 10C22 10.2 24 12.3 24 15C24 17.7 21.7 20 19 20M11 15V17H13V15H11M11 13H13V7H11V13Z" /></svg> \ No newline at end of file
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/cloud.svg b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/cloud.svg
new file mode 100644
index 00000000..ca7a6171
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/cloud.svg
@@ -0,0 +1 @@
+<svg width="32" height="32" fill="none" xmlns="http://www.w3.org/2000/svg"><mask id="a" maskUnits="userSpaceOnUse" x="0" y="5" width="32" height="22"><path fill-rule="evenodd" clip-rule="evenodd" d="M16 5.333c4.853 0 8.893 3.453 9.8 8.053 3.467.24 6.2 3.094 6.2 6.614a6.67 6.67 0 01-6.667 6.666H8c-4.413 0-8-3.586-8-8 0-4.12 3.12-7.52 7.133-7.946A9.994 9.994 0 0116 5.333zM8.667 18l4.666 4.666 8.787-8.786L20.24 12l-6.907 6.906-2.786-2.786L8.667 18z" fill="#fff"></path></mask><g mask="url(#a)"><path fill="#069E08" d="M0 0h32v32H0z"></path></g></svg> \ No newline at end of file
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/jetpack.svg b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/jetpack.svg
new file mode 100644
index 00000000..baf8e47a
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/jetpack.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 480 480" xmlns="http://www.w3.org/2000/svg" width="2500" height="2500"><path d="M252.1 447.56S387.8 188.22 387.35 187.9c.44.32-145.7-.23-146.15-.54.45.3-1.2-161.78-1.2-161.78s-24.73.55-25.16.24c.43.3-130.88 262.4-131.32 262.1.44.3 131.75-.25 131.32-.56.43.3 9.23 156.9 8.8 156.6.43.3 28.45 3.6 28.45 3.6z" fill="#fff"/><path d="M240 0C107.63 0 0 107.63 0 240s107.63 240 240 240 240-107.63 240-240S372.37 0 240 0zm-12.37 279.85H108.1L227.62 47.18v232.67zm24.28 152.52V199.7h119.55L251.9 432.36z" fill="#069e08"/></svg>
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/plugins.svg b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/plugins.svg
new file mode 100644
index 00000000..22419452
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/plugins.svg
@@ -0,0 +1 @@
+<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="4.75" y="7.75" width="14.5" height="10.5" rx="1.25" stroke="#069E08" stroke-width="1.5"></rect><path fill="#069E08" d="M6 5h5v3H6zM13 5h5v3h-5z"></path></svg> \ No newline at end of file
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/posts.svg b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/posts.svg
new file mode 100644
index 00000000..9299c527
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/posts.svg
@@ -0,0 +1 @@
+<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 7L8 13.5c-.167-1.167 1-5.167 1.5-6 .365-.608 1-1.5 2.5-2.5s5-2 5-2c0 1-1 2.5-2.5 4z" fill="#069E08"></path><path d="M7 16l1-2.5m0 0L14.5 7C16 5.5 17 4 17 3c0 0-3.5 1-5 2S9.865 6.892 9.5 7.5c-.5.833-1.667 4.833-1.5 6z" stroke="#069E08" stroke-width="1.5" stroke-linecap="round"></path><path d="M17.743 3.1a.75.75 0 10-1.486-.2l1.486.2zm-1.486-.2c-.089.662-.131 1.443-.17 2.235-.04.804-.075 1.63-.146 2.423-.072.795-.176 1.525-.344 2.134-.17.62-.386 1.036-.627 1.278l1.06 1.06c.509-.508.814-1.216 1.013-1.94.203-.735.317-1.568.392-2.398.074-.831.111-1.694.15-2.483.04-.802.08-1.52.158-2.11l-1.486-.198zm-1.287 8.07c-.276.275-.767.574-1.435.866-.653.287-1.415.541-2.175.754-.758.213-1.502.38-2.114.493-.63.117-1.071.167-1.246.167v1.5c.325 0 .885-.075 1.52-.192a26.28 26.28 0 002.245-.523 18.402 18.402 0 002.372-.825c.722-.316 1.419-.705 1.893-1.18l-1.06-1.06z" fill="#069E08"></path><path stroke="#069E08" stroke-width="1.5" d="M6 19.25h8"></path></svg> \ No newline at end of file
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/themes.svg b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/themes.svg
new file mode 100644
index 00000000..8e3afcae
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/themes.svg
@@ -0,0 +1 @@
+<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M17.44 13.905a5.345 5.345 0 01-10.69 0c0-.652.307-1.557.866-2.619.547-1.039 1.284-2.137 2.034-3.15a47.06 47.06 0 012.445-3.014 48.194 48.194 0 012.445 3.015c.75 1.012 1.488 2.11 2.034 3.15.56 1.061.866 1.966.866 2.618z" stroke="#069E08" stroke-width="1.5"></path></svg> \ No newline at end of file
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/uploads.svg b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/uploads.svg
new file mode 100644
index 00000000..57132bfd
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/icons/uploads.svg
@@ -0,0 +1 @@
+<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M19.293 13.758a7.503 7.503 0 01-14.168 1.243l3.67-2.177 3.456 1.217a.75.75 0 00.686-.098l2.887-2.073.08.04c.296.145.703.349 1.15.58.78.406 1.64.877 2.239 1.268zm.206-1.635a37.63 37.63 0 00-1.754-.964 63.44 63.44 0 00-1.538-.771l-.099-.048-.026-.012-.01-.005a.75.75 0 00-.76.068l-2.932 2.105-3.417-1.203a.75.75 0 00-.631.062l-3.675 2.18A7.5 7.5 0 1119.5 12.123zM21 12a9 9 0 11-18 0 9 9 0 0118 0z" fill="#069E08"></path></svg> \ No newline at end of file
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/masthead/calypso-colors.scss b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/masthead/calypso-colors.scss
new file mode 100644
index 00000000..7237b4d4
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/masthead/calypso-colors.scss
@@ -0,0 +1,60 @@
+// Blues
+$blue-wordpress: #0087be;
+$blue-light: #78dcfa;
+$blue-medium: #3582c4;
+$blue-dark: #005082;
+$blue-medium-dark: #2271b1;
+$blue-grey-light: #f6f7f7;
+$blue-grey-dark: #0a4b78;
+$light-gray-700: #c3c4c7;
+
+
+// Grays
+$gray-original: #87a6bc;
+$gray: desaturate( $gray-original, 100% ); // Intermediary transform to match dotcom's colors
+
+// $gray color functions:
+//
+// lighten( $gray, 10% )
+// lighten( $gray, 20% )
+// lighten( $gray, 30% )
+// darken( $gray, 10% )
+// darken( $gray, 20% )
+// darken( $gray, 30% )
+//
+// See wordpress.com/design-handbook/colors/ for more info.
+
+$gray-light: lighten( $gray, 33% ); //#f6f6f6
+$gray-dark: darken( $gray, 38% ); //#404040
+
+// $gray-text: ideal for standard, non placeholder text
+// $gray-text-min: minimum contrast needed for WCAG 2.0 AA on white background
+$gray-text: $gray-dark;
+$gray-text-min: darken( $gray, 18% ); //#537994
+
+// Shades of gray
+$gray-lighten-10: lighten( $gray, 10% ); // #a8bece
+$gray-lighten-20: lighten( $gray, 20% ); // #c8d7e1
+$gray-lighten-30: lighten( $gray, 30% ); // #e9eff3
+$gray-darken-10: darken( $gray, 10% ); // #668eaa
+$gray-darken-20: darken( $gray, 20% ); // #4f748e
+$gray-darken-30: darken( $gray, 30% ); // #3d596d
+
+// Oranges
+$orange-jazzy: #f0821e;
+$orange-fire: #d63638;
+
+// Alerts
+$alert-yellow: #f0b849;
+$alert-red: #d94f4f;
+$alert-green: #4ab866;
+$alert-purple: #855DA6;
+
+// Link hovers
+$link-highlight: tint($blue-medium, 20%);
+
+// Essentials
+$white: rgba(255,255,255,1);
+$transparent: rgba(255,255,255,0);
+
+$border-ultra-light-gray: #e8f0f5; \ No newline at end of file
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/masthead/calypso-mixins.scss b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/masthead/calypso-mixins.scss
new file mode 100644
index 00000000..7db8b157
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/masthead/calypso-mixins.scss
@@ -0,0 +1,351 @@
+@use "sass:math";
+
+$full-width: 960px;
+$one-col: 660px;
+$mobile: 480px;
+
+$sidebar-width: 269px;
+
+@mixin responsive($width) {
+ @if $width == full-width {
+ @media only screen and (max-width: $full-width) { @content; }
+ }
+ @else if $width == one-col {
+ @media only screen and (max-width: $one-col) { @content; }
+ }
+ @else if $width == mobile {
+ @media only screen and (max-width: $mobile) { @content; }
+ }
+}
+
+@mixin mobile-first-responsive($width) {
+ @if $width == full-width {
+ @media only screen and (min-width: $one-col) { @content; }
+ }
+ @else if $width == full-width-really {
+ @media only screen and (min-width: $full-width) { @content; }
+ }
+ @else if $width == one-col {
+ @media only screen and (min-width: $mobile) { @content; }
+ }
+}
+
+// ==========================================================================
+// Breakpoint Mixin
+// See https://wpcalypso.wordpress.com/devdocs/docs/coding-guidelines/css.md#media-queries
+// ==========================================================================
+
+$breakpoints: 480px, 660px, 960px, 1040px; // Think very carefully before adding a new breakpoint
+
+@mixin breakpoint( $size ){
+ @if type-of($size) == string {
+ $approved-value: 0;
+ @each $breakpoint in $breakpoints {
+ $and-larger: ">" + $breakpoint;
+ $and-smaller: "<" + $breakpoint;
+
+ @if $size == $and-smaller {
+ $approved-value: 1;
+ @media ( max-width: $breakpoint ) {
+ @content;
+ }
+ }
+ @else {
+ @if $size == $and-larger {
+ $approved-value: 2;
+ @media ( min-width: $breakpoint + 1 ) {
+ @content;
+ }
+ }
+ @else {
+ @each $breakpoint-end in $breakpoints {
+ $range: $breakpoint + "-" + $breakpoint-end;
+ @if $size == $range {
+ $approved-value: 3;
+ @media ( min-width: $breakpoint + 1 ) and ( max-width: $breakpoint-end ) {
+ @content;
+ }
+ }
+ }
+ }
+ }
+ }
+ @if $approved-value == 0 {
+ $sizes: "";
+ @each $breakpoint in $breakpoints {
+ $sizes: $sizes + " " + $breakpoint;
+ }
+ // TODO - change this to use @error, when it is supported by node-sass
+ @warn "ERROR in breakpoint( #{ $size } ): You can only use these sizes[ #{$sizes} ] using the following syntax [ <#{ nth( $breakpoints, 1 ) } >#{ nth( $breakpoints, 1 ) } #{ nth( $breakpoints, 1 ) }-#{ nth( $breakpoints, 2 ) } ]";
+ }
+ }
+ @else {
+ $sizes: "";
+ @each $breakpoint in $breakpoints {
+ $sizes: $sizes + " " + $breakpoint;
+ }
+ // TODO - change this to use @error, when it is supported by node-sass
+ @warn "ERROR in breakpoint( #{ $size } ): Please wrap the breakpoint $size in parenthesis. You can use these sizes[ #{$sizes} ] using the following syntax [ <#{ nth( $breakpoints, 1 ) } >#{ nth( $breakpoints, 1 ) } #{ nth( $breakpoints, 1 ) }-#{ nth( $breakpoints, 2 ) } ]";
+ }
+}
+
+
+@mixin calc($property, $expression) {
+ #{$property}: -moz-calc(#{$expression});
+ #{$property}: -o-calc(#{$expression});
+ #{$property}: -webkit-calc(#{$expression});
+ #{$property}: calc(#{$expression});
+}
+
+@mixin clear-fix {
+ &:after {
+ content: ".";
+ display: block;
+ height: 0;
+ clear: both;
+ visibility: hidden;
+ }
+}
+
+@mixin noticon($char, $size: null) {
+ // This isn't very clean, but... we'll see ;)
+ @if $size != 0 {
+ font-size: $size;
+ }
+ content: $char;
+
+ // Copied verbatim
+ vertical-align: top;
+ text-align: center;
+ display: inline-block;
+ font-family: "Noticons";
+ font-style: normal;
+ font-weight: normal;
+ font-variant: normal;
+ line-height: 1;
+ text-decoration: inherit;
+ text-transform: none;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ speak: none;
+}
+
+@mixin border-box {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+// Turn a list into a dropdown menu
+@mixin dropdown-menu {
+ display: none;
+ background: $white;
+ float: none;
+ line-height: 46px;
+ min-width: 220px;
+ overflow: visible;
+ padding: 0;
+ position: absolute;
+ width: auto;
+ z-index: 1;
+ box-sizing: border-box;
+ box-shadow: 0 0 2px rgba(0,0,0,0.15), 0 3px 8px rgba(0,0,0,0.1);
+
+ &:after {
+ border: 6px solid transparent;
+ border-bottom-color: $white;
+ content: ' ';
+ height: 0;
+ position: absolute;
+ top: -12px;
+ left: 73px;
+ width: 0;
+ }
+
+ li {
+ display: block;
+ float: none;
+
+ a,
+ a.selected {
+ border-bottom: 1px solid rgba(0,0,0,0.1);
+ color: $blue-wordpress;
+ display: block;
+ float: none;
+ height: auto;
+ margin: 0;
+ padding: 0 14px;
+ text-align: left;
+
+ &:hover {
+ border-bottom: 1px solid rgba(0,0,0,0.1);
+ background: none; // Remove inherited background color
+ color: $link-highlight;
+ box-shadow: none; // Remove inherited box shadow
+ }
+ }
+
+ a.selected {
+ color: $gray-dark;
+ }
+
+ &:last-child a {
+ border-bottom: none; // Last child in the dropdown doesn't need a bottom border
+ }
+ }
+}
+
+// Can't use the @extend in a media query, use this instead
+@mixin clear-text {
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+// courtesy: http://codeboxers.com/sass-mixin-for-transitions/
+@mixin transition($transition-property, $transition-time, $method) {
+ -webkit-transition: $transition-property $transition-time $method;
+ -moz-transition: $transition-property $transition-time $method;
+ -ms-transition: $transition-property $transition-time $method;
+ -o-transition: $transition-property $transition-time $method;
+ transition: $transition-property $transition-time $method;
+}
+
+@mixin box-shadow($shadows...) {
+ -webkit-box-shadow: $shadows;
+ -moz-box-shadow: $shadows;
+ -ms-box-shadow: $shadows;
+ -o-box-shadow: $shadows;
+ box-shadow: $shadows;
+}
+
+@mixin site-icon($size, $icon-size) {
+ position: relative;
+ display: inline-block;
+ width: $size;
+ height: $size;
+ overflow: hidden;
+ background: lighten( $gray, 20% );
+
+ &::before {
+ content: '\f475';
+ display: inline-block;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ font: normal math.div($icon-size, 1) 'Noticons';
+ color: $white;
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: $size;
+ width: $size;
+ line-height: $size;
+ text-align: center;
+ z-index: 0;
+ }
+
+ img {
+ background: $white;
+ position: relative;
+ }
+}
+
+@mixin debug(){
+ box-shadow: 0px 0px 10px $alert-red inset;
+}
+
+@mixin stats-fade-text($toColor) {
+ background-image: linear-gradient(to right, $transparent 0%, $toColor 90%);
+ position: absolute;
+ z-index: 1;
+ left: -48px;
+ top: 0;
+ bottom: 0;
+ content: "";
+ display: block;
+ width: 48px;
+}
+
+@mixin hide-content-accessibly {
+ clip: rect( 1px, 1px, 1px, 1px );
+ height: 1px;
+ overflow: hidden;
+ position: absolute;
+ width: 1px;
+}
+
+// Creates a fading overlay to signify that the content is longer
+// than the space allows.
+@mixin long-content-fade( $direction: right, $size: 20%, $color: #fff, $edge: 0px, $z-index: false) {
+ content: '';
+ display: block;
+ position: absolute;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ pointer-events: none;
+
+ @if $z-index {
+ z-index: $z-index;
+ }
+
+ @if $direction == 'bottom' {
+ background: linear-gradient( to top, rgba( $color, 0 ), $color 90% );
+ left: $edge;
+ right: $edge;
+ top: $edge;
+ bottom: calc(100% - $size);
+ width: auto;
+ }
+
+ @if $direction == 'top' {
+ background: linear-gradient( to bottom, rgba( $color, 0 ), $color 90% );
+ top: calc(100% - $size);
+ left: $edge;
+ right: $edge;
+ bottom: $edge;
+ width: auto;
+ }
+
+ @if $direction == 'left'{
+ background: linear-gradient( to left, rgba( $color, 0 ), $color 90% );
+ top: $edge;
+ left: $edge;
+ bottom: $edge;
+ right: auto;
+ width: $size;
+ height: auto;
+ }
+
+ @if $direction == 'right' {
+ background: linear-gradient( to right, rgba( $color, 0 ), $color 90% );
+ top: $edge;
+ bottom: $edge;
+ right: $edge;
+ left: auto;
+ width: $size;
+ height: auto;
+ }
+}
+
+@mixin placeholder( $lighten-percentage: 30% ) {
+ animation: loading-fade 1.6s ease-in-out infinite;
+ background-color: lighten( $gray, $lighten-percentage );
+ color: transparent;
+
+ &:after {
+ content: '\00a0';
+ }
+}
+
+// Simple animation to make elements appear
+@keyframes appear {
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/masthead/masthead-style.scss b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/masthead/masthead-style.scss
new file mode 100644
index 00000000..2dc28d05
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/masthead/masthead-style.scss
@@ -0,0 +1,89 @@
+@import './calypso-mixins';
+@import './calypso-colors';
+
+.jp-masthead {
+ padding: 40px 0;
+ background-color: $white;
+ text-align: center;
+ @media (max-width: rem( 782px ) ) {
+ padding: 0 rem( 24px );
+
+ .jetpack-masterbar & {
+ padding-left: rem( 64px );
+ }
+ }
+}
+
+.jp-masthead__inside-container {
+ display: flex;
+ flex-wrap: wrap;
+ margin: 0 auto;
+ width: 100%;
+ max-width: rem( 1040px );
+ padding-bottom: rem( 6px );
+
+ @media (max-width: 1250px) {
+ max-width: 95%;
+ }
+}
+
+.jp-masthead__logo-container {
+ flex-grow: 0;
+ flex-shrink: 0;
+ padding: rem( 11px ) 0 0;
+
+ @include breakpoint( "<480px" ) {
+ margin-right: rem( 16px );
+ }
+}
+
+.jp-masthead__logo-link {
+ display: inline-block;
+ outline: none;
+ vertical-align: middle;
+
+ &:focus {
+ line-height: 0; // fixes rectangle gap
+ box-shadow: 0 0 0 2px $blue-light;
+ }
+
+ & + code {
+ margin: 0 10px;
+ padding: 5px 9px;
+ border-radius: 2px;
+ background: #e6ecf1;
+ color: #647a88;
+ }
+}
+
+.jp-masthead__nav {
+ display: flex;
+ flex-wrap: nowrap;
+ flex-grow: 1;
+ flex-shrink: 0;
+ text-align: right;
+ margin-top: rem( 6px );
+ padding: rem( 4px ) 0;
+
+ .dops-button-group {
+ flex-grow: 1;
+ align-self: center;
+ /* This fixes an unwanted space between the buttons in the network settings caused by a line break. */
+ /* Fixed here to keep PHP code readable. It's safe: .dops-button and .dops-button.is-compact specify a font size. */
+ font-size: 0;
+ }
+ @include breakpoint( "<480px" ) {
+ text-align: left;
+ }
+}
+
+#sandbox-domain-badge {
+ background: #d63638;
+ text-transform: uppercase;
+ letter-spacing: 0.2em;
+ text-shadow: none;
+ font-size: 9px;
+ font-weight: bold;
+ cursor: pointer;
+ color: #ffffff;
+}
diff --git a/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/stat-block-style.scss b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/stat-block-style.scss
new file mode 100644
index 00000000..469e292b
--- /dev/null
+++ b/plugins/jetpack/jetpack_vendor/automattic/jetpack-backup/src/js/components/stat-block-style.scss
@@ -0,0 +1,46 @@
+.stat-block {
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+
+ .icon {
+ img {
+ margin-top: 24px;
+ height: 24px;
+ width: 24px;
+ }
+ flex: 2;
+ }
+
+ .label {
+ flex: 1;
+ font-weight: bold;
+ }
+
+ .value {
+ flex: 1;
+ }
+
+ .large-text {
+ font-size: 2em;
+ font-weight: bold;
+ }
+}
+
+.backup__card {
+ padding: 24px;
+ background:var( --jp-white );
+ box-shadow: 0px 0px 40px rgba( 0, 0, 0, 0.08 );
+ border-radius: var( --jp-border-radius );
+}
+
+.backup__card-details-items {
+ margin: 16px 0 -8px;
+ font-weight: 500;
+}
+
+.backup__card-details-amount {
+ margin-bottom: -12px;
+ font-size: var( --font-title-large );
+ font-weight: 600;
+} \ No newline at end of file