Skip to content

Commit

Permalink
Merge pull request #2684 from woocommerce/add/support-core-gtin-field
Browse files Browse the repository at this point in the history
Support core gtin field
  • Loading branch information
puntope authored Nov 22, 2024
2 parents 64acb11 + 934d0bc commit 5d03086
Show file tree
Hide file tree
Showing 32 changed files with 1,638 additions and 17 deletions.
174 changes: 174 additions & 0 deletions js/src/components/gtin-migration-banner/gtin-migration-banner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { Notice } from '@wordpress/components';
import { createInterpolateElement, useState } from '@wordpress/element';

/**
* Internal dependencies
*/
import TrackableLink from '.~/components/trackable-link';
import AppButton from '.~/components/app-button';
import AppModal from '.~/components/app-modal';
import { recordGlaEvent } from '.~/utils/tracks';
import useDispatchCoreNotices from '.~/hooks/useDispatchCoreNotices';
import useGTINMigrationStatus from '.~/hooks/useGTINMigrationStatus';
import './index.scss';

const GTIN_MIGRATION_BANNER_CONTEXT = 'gtin_migration_banner';
const GTIN_MIGRATION_READY = 'ready';
const GTIN_MIGRATION_STARTED = 'started';

const LinkGTINMigrationJobStatusPage = ( props ) => (
<TrackableLink
eventName="gla_gtin_migration_banner_status_link_click"
eventProps={ {
context: GTIN_MIGRATION_BANNER_CONTEXT,
} }
href={
'admin.php?page=wc-status&tab=action-scheduler&s=migrate_gtin&orderby=schedule&order=desc'
}
type="external"
target="_blank"
{ ...props }
/>
);

const GtinMigrationBanner = () => {
const { createNotice } = useDispatchCoreNotices();
const [ showModal, setShowModal ] = useState( false );
const [ status, loading, startMigration ] = useGTINMigrationStatus();

if (
status !== GTIN_MIGRATION_READY &&
status !== GTIN_MIGRATION_STARTED
) {
return null;
}

const closeModal = () => {
recordGlaEvent( 'gla_modal_closed', {
context: GTIN_MIGRATION_BANNER_CONTEXT,
} );
setShowModal( false );
};

const openModal = () => {
recordGlaEvent( 'gla_modal_open', {
context: GTIN_MIGRATION_BANNER_CONTEXT,
} );
setShowModal( true );
};

const handleStartMigrationClick = async () => {
recordGlaEvent( 'gla_gtin_migration_banner_migration_start', {
context: GTIN_MIGRATION_BANNER_CONTEXT,
} );
try {
await startMigration();
recordGlaEvent( 'gla_gtin_migration_banner_migration_scheduled', {
context: GTIN_MIGRATION_BANNER_CONTEXT,
} );
setShowModal( false );
createNotice(
'info',
__(
'GTIN Migration was successfully scheduled.',
'google-listings-and-ads'
)
);
} catch ( e ) {
recordGlaEvent( 'gla_gtin_migration_banner_migration_failed', {
context: GTIN_MIGRATION_BANNER_CONTEXT,
error: e.message,
} );
createNotice(
'error',
__(
'Unable to start GTIN Migration.',
'google-listings-and-ads'
)
);
}
};

return (
<>
{ showModal && (
<AppModal
className="gla-gtin-migration-banner-modal"
title={ __(
'Before you start the migration…',
'google-listings-and-ads'
) }
buttons={ [
<AppButton key="1" isSecondary onClick={ closeModal }>
{ __( 'Never mind', 'google-listings-and-ads' ) }
</AppButton>,
<AppButton
key="2"
disabled={ loading }
isPrimary
onClick={ handleStartMigrationClick }
>
{ __(
'Start migration',
'google-listings-and-ads'
) }
</AppButton>,
] }
onRequestClose={ closeModal }
>
<p>
{ createInterpolateElement(
__(
"This migration will copy all GTIN numbers set in the Google for WooCommerce Product tab into the new GTIN field under the Product Inventory tab. If you have already set GTIN numbers in some of your products' Inventory tab, they will not be overridden. The GTIN numbers in the Google for WooCommerce tab will not be removed. The migration will run in the background and is not reversible. You can check the migration process on the <link>WooCommerce Scheduled Actions page</link>.",
'google-listings-and-ads'
),
{
link: <LinkGTINMigrationJobStatusPage />,
}
) }
</p>
</AppModal>
) }
{ status === GTIN_MIGRATION_READY && (
<Notice isDismissible={ false }>
{ createInterpolateElement(
__(
"The GTIN field managed by WooCommerce in the Product's inventory section, will now be used by Google for WooCommerce. It will continue to support the previous field and any mapping rules you have setup for the GTIN field. If you would like to migrate the data <link>click here</link>.",
'google-listings-and-ads'
),
{
link: (
<TrackableLink
className="gla-gtin-migration__link"
eventName="gla_gtin_migration_banner_click"
eventProps={ {
context: GTIN_MIGRATION_BANNER_CONTEXT,
} }
onClick={ openModal }
/>
),
}
) }
</Notice>
) }
{ status === GTIN_MIGRATION_STARTED && (
<Notice isDismissible={ false }>
{ createInterpolateElement(
__(
'Your GTIN Migration is now running in the background. You can check the migration process on the <link>WooCommerce Scheduled Actions page</link>',
'google-listings-and-ads'
),
{
link: <LinkGTINMigrationJobStatusPage />,
}
) }
</Notice>
) }
</>
);
};
export default GtinMigrationBanner;
1 change: 1 addition & 0 deletions js/src/components/gtin-migration-banner/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './gtin-migration-banner';
6 changes: 6 additions & 0 deletions js/src/components/gtin-migration-banner/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.gla-gtin-migration {
&__link {
cursor: pointer;
text-decoration: underline;
}
}
9 changes: 7 additions & 2 deletions js/src/components/main-tab-nav/main-tab-nav.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getNewPath, getPath } from '@woocommerce/navigation';
import { glaData } from '.~/constants';
import AppTabNav from '.~/components/app-tab-nav';
import useMenuEffect from '.~/hooks/useMenuEffect';
import GtinMigrationBanner from '.~/components/gtin-migration-banner';

let tabs = [
{
Expand Down Expand Up @@ -55,7 +56,11 @@ const MainTabNav = () => {

const selectedKey = getSelectedTabKey();

return <AppTabNav tabs={ tabs } selectedKey={ selectedKey } />;
return (
<>
<GtinMigrationBanner />
<AppTabNav tabs={ tabs } selectedKey={ selectedKey } />
</>
);
};

export default MainTabNav;
7 changes: 7 additions & 0 deletions js/src/dashboard/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ import isWCTracksEnabled from '.~/utils/isWCTracksEnabled';
import RebrandingTour from '.~/components/tours/rebranding-tour';
import { GUIDE_NAMES } from '.~/constants';

jest.mock( '.~/hooks/useGTINMigrationStatus', () =>
jest
.fn()
.mockReturnValue( [ 'completed', false, jest.fn() ] )
.mockName( 'useGTINMigrationStatus' )
);

jest.mock( '.~/components/different-currency-notice', () =>
jest.fn().mockName( 'DifferentCurrencyNotice' )
);
Expand Down
1 change: 1 addition & 0 deletions js/src/data/action-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const TYPES = {
UPSERT_TOUR: 'UPSERT_TOUR',
HYDRATE_PREFETCHED_DATA: 'HYDRATE_PREFETCHED_DATA',
RECEIVE_GOOGLE_ADS_ACCOUNT_STATUS: 'RECEIVE_GOOGLE_ADS_ACCOUNT_STATUS',
RECEIVE_GTIN_MIGRATION_STATUS: 'RECEIVE_GTIN_MIGRATION_STATUS',
};

export default TYPES;
12 changes: 12 additions & 0 deletions js/src/data/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1266,6 +1266,18 @@ export function* upsertTour( tour, upsertingClientStoreFirst = false ) {
}
}

/**
* Action to receive the GTIN Migration status.
*
* @param {string} status GTIN Migration status
*/
export function* receiveGtinMigrationStatus( status ) {
return {
type: TYPES.RECEIVE_GTIN_MIGRATION_STATUS,
data: status,
};
}

export function* fetchGoogleAdsAccountStatus() {
try {
const data = yield apiFetch( {
Expand Down
6 changes: 6 additions & 0 deletions js/src/data/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const DEFAULT_STATE = {
step: null,
},
},
gtinMigrationStatus: null,
};

/**
Expand Down Expand Up @@ -510,6 +511,11 @@ const reducer = ( state = DEFAULT_STATE, action ) => {
.end();
}

case TYPES.RECEIVE_GTIN_MIGRATION_STATUS: {
const { data } = action;
return setIn( state, 'gtinMigrationStatus', data?.status );
}

// Page will be reloaded after all accounts have been disconnected, so no need to mutate state.
case TYPES.DISCONNECT_ACCOUNTS_ALL:
default:
Expand Down
22 changes: 22 additions & 0 deletions js/src/data/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
receiveMappingRules,
receiveStoreCategories,
receiveTour,
receiveGtinMigrationStatus,
} from './actions';

export function* getShippingRates() {
Expand Down Expand Up @@ -534,3 +535,24 @@ export function* getGoogleAdsAccountStatus() {
getGoogleAdsAccountStatus.shouldInvalidate = ( action ) => {
return action.type === TYPES.DISCONNECT_ACCOUNTS_GOOGLE_ADS;
};

/**
* Resolver for getting the GTIN Migration status.
*/
export function* getGtinMigrationStatus() {
try {
const response = yield apiFetch( {
path: `${ API_NAMESPACE }/gtin-migration`,
} );

yield receiveGtinMigrationStatus( response );
} catch ( error ) {
handleApiError(
error,
__(
'There was an error getting the GTIN Migration Status.',
'google-listings-and-ads'
)
);
}
}
10 changes: 10 additions & 0 deletions js/src/data/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,3 +410,13 @@ export const getTour = ( state, tourId ) => {
export const getGoogleAdsAccountStatus = ( state ) => {
return state.ads.accountStatus;
};

/**
* Return the GTIN Migration status.
*
* @param {Object} state The state
* @return {Object} The GTIN Migration status.
*/
export const getGtinMigrationStatus = ( state ) => {
return state.gtinMigrationStatus;
};
1 change: 1 addition & 0 deletions js/src/data/test/reducer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ describe( 'reducer', () => {
step: null,
},
},
gtinMigrationStatus: null,
} );

prepareState = prepareImmutableStateWithRefCheck.bind(
Expand Down
33 changes: 33 additions & 0 deletions js/src/hooks/useGTINMigrationStatus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* External dependencies
*/
import { useCallback } from '@wordpress/element';

/**
* Internal dependencies
*/
import useAppSelectDispatch from '.~/hooks/useAppSelectDispatch';
import useApiFetchCallback from '.~/hooks/useApiFetchCallback';

const selectorName = 'getGtinMigrationStatus';

const useGTINMigrationStatus = () => {
const { data, isResolving, invalidateResolution } =
useAppSelectDispatch( selectorName );

const [ startMigrationApiCall, { loading } ] = useApiFetchCallback( {
path: `/wc/gla/gtin-migration`,
method: 'POST',
} );

const isLoading = loading || isResolving;

const startMigration = useCallback( async () => {
await startMigrationApiCall();
invalidateResolution();
}, [ startMigrationApiCall, invalidateResolution ] );

return [ data, isLoading, startMigration ];
};

export default useGTINMigrationStatus;
Loading

0 comments on commit 5d03086

Please sign in to comment.