dev/refactor core profiler utils (#39581)

* dev: added useFullScreen hook

- foresee using this in more developments

* dev: made findComponentMeta generic

* changelog
This commit is contained in:
RJ 2023-08-15 21:26:37 +10:00 committed by GitHub
parent 45c49dc232
commit 964dd1f449
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 78 additions and 56 deletions

View File

@ -38,6 +38,7 @@ import { getAdminLink } from '@woocommerce/settings';
/** /**
* Internal dependencies * Internal dependencies
*/ */
import { findComponentMeta } from '~/utils/xstate/find-component';
import { IntroOptIn } from './pages/IntroOptIn'; import { IntroOptIn } from './pages/IntroOptIn';
import { import {
UserProfile, UserProfile,
@ -54,7 +55,7 @@ import { BusinessLocation } from './pages/BusinessLocation';
import { getCountryStateOptions } from './services/country'; import { getCountryStateOptions } from './services/country';
import { Loader } from './pages/Loader'; import { Loader } from './pages/Loader';
import { Plugins } from './pages/Plugins'; import { Plugins } from './pages/Plugins';
import { getPluginSlug } from '~/utils'; import { getPluginSlug, useFullScreen } from '~/utils';
import './style.scss'; import './style.scss';
import { import {
InstallationCompletedResult, InstallationCompletedResult,
@ -64,7 +65,7 @@ import {
} from './services/installAndActivatePlugins'; } from './services/installAndActivatePlugins';
import { ProfileSpinner } from './components/profile-spinner/profile-spinner'; import { ProfileSpinner } from './components/profile-spinner/profile-spinner';
import recordTracksActions from './actions/tracks'; import recordTracksActions from './actions/tracks';
import { findComponentMeta } from './utils/find-component'; import { ComponentMeta } from './types';
export type InitializationCompleteEvent = { export type InitializationCompleteEvent = {
type: 'INITIALIZATION_COMPLETE'; type: 'INITIALIZATION_COMPLETE';
@ -1437,7 +1438,7 @@ export const CoreProfilerController = ( {
// eslint-disable-next-line react-hooks/exhaustive-deps -- false positive due to function name match, this isn't from react std lib // eslint-disable-next-line react-hooks/exhaustive-deps -- false positive due to function name match, this isn't from react std lib
const currentNodeMeta = useSelector( service, ( currentState ) => const currentNodeMeta = useSelector( service, ( currentState ) =>
findComponentMeta( currentState?.meta ?? undefined ) findComponentMeta< ComponentMeta >( currentState?.meta ?? undefined )
); );
const navigationProgress = currentNodeMeta?.progress; const navigationProgress = currentNodeMeta?.progress;
@ -1455,19 +1456,7 @@ export const CoreProfilerController = ( {
? Object.keys( state.value )[ 0 ] ? Object.keys( state.value )[ 0 ]
: state.value; : state.value;
useEffect( () => { useFullScreen( [ 'woocommerce-profile-wizard__body' ] );
document.body.classList.remove( 'woocommerce-admin-is-loading' );
document.body.classList.add( 'woocommerce-profile-wizard__body' );
document.body.classList.add( 'woocommerce-admin-full-screen' );
document.body.classList.add( 'is-wp-toolbar-disabled' );
return () => {
document.body.classList.remove(
'woocommerce-profile-wizard__body'
);
document.body.classList.remove( 'woocommerce-admin-full-screen' );
document.body.classList.remove( 'is-wp-toolbar-disabled' );
};
} );
return ( return (
<> <>

View File

@ -0,0 +1,17 @@
/**
* Internal dependencies
*/
import { CoreProfilerStateMachineContext } from '.';
export type ComponentMeta = {
/** React component that is rendered when state matches the location this meta key is defined */
component: ( arg0: ComponentProps ) => JSX.Element;
/** number between 0 - 100 */
progress: number;
};
export type ComponentProps = {
navigationProgress: number | undefined;
sendEvent: unknown;
context: CoreProfilerStateMachineContext;
};

View File

@ -1,39 +0,0 @@
/**
* Internal dependencies
*/
import { CoreProfilerStateMachineContext } from '..';
export type ComponentMeta = {
/** React component that is rendered when state matches the location this meta key is defined */
component: ( arg0: ComponentProps ) => JSX.Element;
/** number between 0 - 100 */
progress: number;
};
export type ComponentProps = {
navigationProgress: number | undefined;
sendEvent: unknown;
context: CoreProfilerStateMachineContext;
};
/**
* Does a depth-first search of a meta object to find the first instance of a component.
*/
export function findComponentMeta(
obj: Record< string, unknown >
): ComponentMeta | undefined {
for ( const key in obj ) {
if ( key === 'component' ) {
return obj as ComponentMeta;
} else if ( typeof obj[ key ] === 'object' && obj[ key ] !== null ) {
const found = findComponentMeta(
obj[ key ] as Record< string, unknown >
);
if ( found !== undefined ) {
return found;
}
}
}
return undefined;
}

View File

@ -1,3 +1,8 @@
/**
* External dependencies
*/
import { useEffect } from '@wordpress/element';
export * from './plugins'; export * from './plugins';
export * from './slot-fill-ordering'; export * from './slot-fill-ordering';
@ -91,3 +96,22 @@ export const getTimeFrame = ( timeInMs ) => {
} }
} }
}; };
/**
* Goes into fullscreen mode when the component is loaded
*
* @param {string[]} classes - classes to add to document.body
*/
export const useFullScreen = ( classes ) => {
useEffect( () => {
document.body.classList.remove( 'woocommerce-admin-is-loading' );
document.body.classList.add( classes );
document.body.classList.add( 'woocommerce-admin-full-screen' );
document.body.classList.add( 'is-wp-toolbar-disabled' );
return () => {
document.body.classList.remove( classes );
document.body.classList.remove( 'woocommerce-admin-full-screen' );
document.body.classList.remove( 'is-wp-toolbar-disabled' );
};
} );
};

View File

@ -0,0 +1,23 @@
/**
* Does a depth-first search of a meta object to find the first instance of a component.
*
* @template T - The type of the component meta object
*/
export function findComponentMeta< T >(
obj: Record< string, unknown >
): T | undefined {
for ( const key in obj ) {
if ( key === 'component' ) {
return obj as T;
} else if ( typeof obj[ key ] === 'object' && obj[ key ] !== null ) {
const found = findComponentMeta< T >(
obj[ key ] as Record< string, unknown >
);
if ( found !== undefined ) {
return found;
}
}
}
return undefined;
}

View File

@ -1,7 +1,11 @@
/** /**
* Internal dependencies * Internal dependencies
*/ */
import { findComponentMeta, ComponentProps } from '../find-component'; import { findComponentMeta } from '../find-component';
type ComponentProps = {
context: string;
};
describe( 'findComponentMeta', () => { describe( 'findComponentMeta', () => {
it( 'should return the whole object once "component" key is found in a nested object', () => { it( 'should return the whole object once "component" key is found in a nested object', () => {

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Refactored some core profiler utils out to reuse them in customise your store.