Skip to content

Commit

Permalink
Enabling Staging Site Syncing for WooCommerce (#94280)
Browse files Browse the repository at this point in the history
* Spin up 'Staging Site Syncing for WooCommerce
' branch

* Add allow_woo_sync param on usePullFromStagingMutation API call.

* Style sync warning and display only for woo sites

* Display add staging site warning only when the site has WooCommerce installed; Style the warning message;

* Fix typo

* Send allow_woo_sync on request.

* Apply styling to the "WooCommerce overwrite" text

* Add placeholder `CheckboxControl` component

* Send allow_woo_sync as binary value

* Introduce `disallowWooCommerceSync` logic

* Disable Synchronize button until confirmation checkbox is checked.

---------

Co-authored-by: Yan Sern <yansern@yan.sr>
Co-authored-by: Paulo Cruz <paulo.cruz@automattic.com>
Co-authored-by: Maciej Grabowski <littlesoldiergraba@gmail.com>
Co-authored-by: Ivan Ottinger <25105483+ivan-ottinger@users.noreply.github.com>
  • Loading branch information
5 people authored Sep 11, 2024
1 parent 7a4f12e commit 517e35c
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -1,19 +1,41 @@
import config from '@automattic/calypso-config';
import { Button } from '@automattic/components';
import { useHasEnTranslation } from '@automattic/i18n-utils';
import styled from '@emotion/styled';
import { useTranslate } from 'i18n-calypso';
import { HostingCardDescription } from 'calypso/components/hosting-card';
import InlineSupportLink from 'calypso/components/inline-support-link';
import { useSelector } from 'calypso/state';
import isSiteStore from 'calypso/state/selectors/is-site-store';
import { ExceedQuotaErrorContent } from './exceed-quota-error-content';

const WarningContainer = styled.div( {
marginTop: '16px',
padding: '16px',
marginBottom: '24px',
border: '1px solid #f0c930',
borderRadius: '4px',
} );

const WarningTitle = styled.p( {
fontWeight: 500,
marginBottom: '8px',
} );

const WarningDescription = styled.p( {
marginBottom: '8px',
} );

type CardContentProps = {
siteId: number;
onAddClick: () => void;
isButtonDisabled: boolean;
showQuotaError: boolean;
isDevelopmentSite?: boolean;
};

export const NewStagingSiteCardContent = ( {
siteId,
onAddClick,
isButtonDisabled,
showQuotaError,
Expand All @@ -23,6 +45,7 @@ export const NewStagingSiteCardContent = ( {
const translate = useTranslate();
const hasEnTranslation = useHasEnTranslation();
const stagingSiteSyncWoo = config.isEnabled( 'staging-site-sync-woo' );
const isSiteWooStore = !! useSelector( ( state ) => isSiteStore( state, siteId ) );

return (
<>
Expand Down Expand Up @@ -51,10 +74,10 @@ export const NewStagingSiteCardContent = ( {
}
) }
</HostingCardDescription>
{ stagingSiteSyncWoo && (
<div>
<p>{ translate( 'WooCommerce Site' ) }</p>
<p>
{ stagingSiteSyncWoo && isSiteWooStore && (
<WarningContainer>
<WarningTitle>{ translate( 'WooCommerce Site' ) }</WarningTitle>
<WarningDescription>
{ translate(
'Syncing staging database to production overwrites posts, pages, products and orders. {{a}}Learn more{{/a}}.',
{
Expand All @@ -65,8 +88,8 @@ export const NewStagingSiteCardContent = ( {
},
}
) }
</p>
</div>
</WarningDescription>
</WarningContainer>
) }
{ isDevelopmentSite && (
// Not wrapped in translation to avoid request unconfirmed copy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,28 @@ const OptionsTreeTitle = styled.p( {
marginBottom: '16px',
} );

const SyncWarningContainer = styled.div( {
display: 'flex',
flexDirection: 'column',
border: '1px solid #D63638',
borderRadius: '4px',
maxWidth: '807px',
padding: '16px',
marginBottom: '16px',
} );

const SyncWarningTitle = styled.p( {
fontWeight: 600,
marginTop: '0px',
marginBottom: '8px',
color: '#D63638',
} );

const SyncWarningContent = styled.p( {
marginTop: '0px',
marginBottom: '0px',
} );

interface SyncCardProps {
type: 'production' | 'staging';
onPull: ( ( items?: string[] ) => void ) | ( () => void );
Expand All @@ -139,16 +161,24 @@ const StagingToProductionSync = ( {
onConfirm,
showSyncPanel,
isSqlsOptionDisabled,
isSiteWooStore,
databaseSyncConfirmed,
setdatabaseSyncConfirmed,
isSqlSyncOptionChecked,
}: {
disabled: boolean;
siteSlug: string;
isSyncInProgress: boolean;
onSelectItems: ( items: CheckboxOptionItem[] ) => void;
databaseSyncConfirmed: boolean;
setdatabaseSyncConfirmed: ( value: boolean ) => void;
selectedItems: CheckboxOptionItem[];
isSyncButtonDisabled: boolean;
onConfirm: () => void;
showSyncPanel: boolean;
isSqlsOptionDisabled: boolean;
isSiteWooStore?: boolean;
isSqlSyncOptionChecked?: boolean;
} ) => {
const [ typedSiteName, setTypedSiteName ] = useState( '' );
const translate = useTranslate();
Expand Down Expand Up @@ -221,6 +251,10 @@ const StagingToProductionSync = ( {
disabled={ disabled }
onChange={ onSelectItems }
isSqlsOptionDisabled={ isSqlsOptionDisabled }
databaseSyncConfirmed={ databaseSyncConfirmed }
setdatabaseSyncConfirmed={ setdatabaseSyncConfirmed }
isSiteWooStore={ !! isSiteWooStore }
isSqlSyncOptionChecked={ !! isSqlSyncOptionChecked }
></SyncOptionsPanel>
</>
) }
Expand All @@ -242,15 +276,15 @@ const StagingToProductionSync = ( {
return <li key={ item.name }>{ item.label }</li>;
} ) }
</ConfirmationModalList>
{ stagingSiteSyncWoo && (
<div>
<p>{ translate( 'Warning' ) }</p>
<p>
{ stagingSiteSyncWoo && isSiteWooStore && isSqlSyncOptionChecked && (
<SyncWarningContainer>
<SyncWarningTitle>{ translate( 'Warning:' ) }</SyncWarningTitle>
<SyncWarningContent>
{ translate(
'We do not recommend syncing or pushing data from a staging site to live production news sites or sites that use eCommerce plugins, such as WooCommerce, without proper planning and testing. Keep in mind that data on the destination site could have newer transactions, such as customers and orders, and would be lost when overwritten by the staging site’s data.'
) }
</p>
</div>
</SyncWarningContent>
</SyncWarningContainer>
) }
<ConfirmationModalInputTitle>
{ translate( "Enter your site's name {{span}}%(siteSlug)s{{/span}} to confirm.", {
Expand Down Expand Up @@ -444,9 +478,11 @@ export const SiteSyncCard = ( {
[] as CheckboxOptionItem[]
);
const [ selectedOption, setSelectedOption ] = useState< string | null >( null );
const [ databaseSyncConfirmed, setdatabaseSyncConfirmed ] = useState< boolean >( false );
const siteSlug = useSelector(
type === 'staging' ? ( state ) => getSiteSlug( state, productionSiteId ) : getSelectedSiteSlug
);

const isSiteWooStore = !! useSelector( ( state ) => isSiteStore( state, productionSiteId ) );
const {
progress,
Expand Down Expand Up @@ -488,10 +524,25 @@ export const SiteSyncCard = ( {
}
}, [ resetSyncStatus, dispatch, type, onPull, transformSelectedItems, selectedItems ] );

const isSqlSyncOptionChecked = selectedItems.some( ( item ) => item.name === 'sqls' );

useEffect( () => {
if ( ! isSqlSyncOptionChecked && databaseSyncConfirmed ) {
setdatabaseSyncConfirmed( false );
}
}, [ isSqlSyncOptionChecked, databaseSyncConfirmed, setdatabaseSyncConfirmed ] );

const disallowWooCommerceSync =
config.isEnabled( 'staging-site-sync-woo' ) &&
isSiteWooStore &&
isSqlSyncOptionChecked &&
! databaseSyncConfirmed;

const isSyncButtonDisabled =
disabled ||
( selectedItems.length === 0 && selectedOption === actionForType ) ||
selectedOption === null;
selectedOption === null ||
disallowWooCommerceSync;

let siteToSync: 'production' | 'staging' | null = null;
if ( targetSite ) {
Expand All @@ -512,6 +563,8 @@ export const SiteSyncCard = ( {
}
}, [ dispatch, selectedOption, status, syncError ] );

const stagingSiteSyncWoo = config.isEnabled( 'staging-site-sync-woo' );

return (
<SyncCardContainer
currentSiteType={ type }
Expand Down Expand Up @@ -571,7 +624,11 @@ export const SiteSyncCard = ( {
selectedItems={ selectedItems }
isSyncButtonDisabled={ isSyncButtonDisabled }
onConfirm={ selectedOption === 'push' ? onPushInternal : onPullInternal }
isSqlsOptionDisabled={ isSiteWooStore }
isSqlsOptionDisabled={ stagingSiteSyncWoo ? false : isSiteWooStore }
isSiteWooStore={ isSiteWooStore }
databaseSyncConfirmed={ databaseSyncConfirmed }
setdatabaseSyncConfirmed={ setdatabaseSyncConfirmed }
isSqlSyncOptionChecked={ isSqlSyncOptionChecked }
/>
) }
{ selectedOption !== actionForType && (
Expand Down
1 change: 1 addition & 0 deletions client/my-sites/hosting/staging-site-card/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ export const StagingSiteCard = ( {
} else if ( showAddStagingSiteCard ) {
stagingSiteCardContent = (
<NewStagingSiteCardContent
siteId={ siteId }
onAddClick={ onAddClick }
isDevelopmentSite={ isDevelopmentSite }
isButtonDisabled={
Expand Down
39 changes: 25 additions & 14 deletions client/my-sites/hosting/staging-site-card/sync-options-panel.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import config from '@automattic/calypso-config';
import styled from '@emotion/styled';
import { ToggleControl } from '@wordpress/components';
import { ToggleControl, CheckboxControl } from '@wordpress/components';
import { translate } from 'i18n-calypso';
import { useState, useEffect, useMemo } from 'react';
import InlineSupportLink from 'calypso/components/inline-support-link';

const DangerousItemsContainer = styled.div( {
marginTop: '16px',
Expand All @@ -23,6 +22,11 @@ const DangerousItemsTitle = styled.p( {
color: '#D63638',
} );

const WooCommerceOverwriteWarning = styled.p( {
color: '#D63638',
marginTop: '1.5em',
} );

const ToggleControlWithHelpMargin = styled( ToggleControl )( {
'.components-base-control__help': {
marginLeft: '44px',
Expand Down Expand Up @@ -66,12 +70,20 @@ export default function SyncOptionsPanel( {
disabled,
onChange,
isSqlsOptionDisabled,
isSiteWooStore,
databaseSyncConfirmed,
setdatabaseSyncConfirmed,
isSqlSyncOptionChecked,
}: {
items: CheckboxOptionItem[];
reset: boolean;
disabled: boolean;
onChange: ( items: CheckboxOptionItem[] ) => void;
isSqlsOptionDisabled: boolean;
isSiteWooStore: boolean;
databaseSyncConfirmed: boolean;
isSqlSyncOptionChecked: boolean;
setdatabaseSyncConfirmed: ( value: boolean ) => void;
} ) {
const initialItemsMap = useMemo(
() =>
Expand Down Expand Up @@ -189,21 +201,20 @@ export default function SyncOptionsPanel( {
</div>
);
} ) }
{ stagingSiteSyncWoo && (
{ stagingSiteSyncWoo && isSiteWooStore && (
<div>
<p>
<WooCommerceOverwriteWarning>
{ translate(
'This site has WooCommerce installed. All orders in the production database will be overwritten. {{a}}Learn more{{/a}}.',
{
components: {
a: (
<InlineSupportLink supportContext="hosting-staging-site" showIcon={ false } />
),
},
}
'This site has WooCommerce installed. All orders in the production database will be overwritten.'
) }
</p>
<p>{ translate( 'Confirm I want to proceed with database synchronization ' ) }</p>
</WooCommerceOverwriteWarning>
<CheckboxControl
key="checkbox"
label={ translate( 'Confirm I want to proceed with database synchronization ' ) }
checked={ databaseSyncConfirmed }
disabled={ ! isSqlSyncOptionChecked }
onChange={ setdatabaseSyncConfirmed }
/>
</div>
) }
</DangerousItemsContainer>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import config from '@automattic/calypso-config';
import { useMutation, UseMutationOptions, useIsMutating } from '@tanstack/react-query';
import { useCallback } from 'react';
import wp from 'calypso/lib/wp';
Expand Down Expand Up @@ -52,14 +53,16 @@ export const usePullFromStagingMutation = (
MutationVariables
>
) => {
const isStagingSiteSyncWooEnabled = config.isEnabled( 'staging-site-sync-woo' );

const mutation = useMutation( {
mutationFn: async ( options ) =>
wp.req.post(
{
path: `/sites/${ productionSiteId }/staging-site/pull-from-staging/${ stagingSiteId }`,
apiNamespace: 'wpcom/v2',
},
{ options }
{ options, allow_woo_sync: isStagingSiteSyncWooEnabled ? 1 : 0 }
),
...options,
mutationKey: [ PULL_FROM_STAGING, stagingSiteId ],
Expand Down

0 comments on commit 517e35c

Please sign in to comment.