Skip to content

Commit

Permalink
File structure and components refactoring and test update (#215)
Browse files Browse the repository at this point in the history
* Rename the original utilities.js to common.js to indicate its generic use

* Move the customized hook "useUser" to hooks/

* Move tests/ directory outside of components/

* Separate useUser from common.test

* Add renderHook for useUser test.

The hook should be called by a component. In a test, renderHook would do that for us.

* Extract ScreenNavigation

* Add navigateToScreen as dependency

navigateToScreen should be added as the hook dependency, or hasEdits might not be the latest value when calling the function. In fact, due to the property of how hasEdits is updated, the navigateToScreen would always get the latest value of hasEdits, but it's best practice to add state and props that are used in the hook as its dependency, or it might get harder to develop a new feature or maintain the code someday in the future.

* Bump @wordpress/scripts version to ^25.0.0

See details at #215 (comment)
  • Loading branch information
renintw authored Jun 15, 2023
1 parent 610da2c commit 2f6c51e
Show file tree
Hide file tree
Showing 19 changed files with 450 additions and 202 deletions.
2 changes: 1 addition & 1 deletion settings/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"@wordpress/data": "^8.4.0",
"@wordpress/element": "^5.4.0",
"@wordpress/icons": "^9.18.0",
"@wordpress/scripts": "^24.6.0",
"@wordpress/scripts": "^25.0.0",
"lodash": "^4.17.21"
}
}
2 changes: 1 addition & 1 deletion settings/src/components/backup-codes.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Icon, warning, cancelCircleFilled } from '@wordpress/icons';
* Internal dependencies
*/
import { GlobalContext } from '../script';
import { refreshRecord } from '../utilities';
import { refreshRecord } from '../utilities/common';

/**
* Setup and manage backup codes.
Expand Down
13 changes: 8 additions & 5 deletions settings/src/components/revalidate-modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ import { useCallback, useContext, useEffect, useRef } from '@wordpress/element';
import { GlobalContext } from '../script';
import { Modal } from '@wordpress/components';
import { useMergeRefs, useFocusableIframe } from '@wordpress/compose';
import { refreshRecord } from '../utilities';
import { refreshRecord } from '../utilities/common';

export default function RevalidateModal() {
const { navigateToScreen } = useContext( GlobalContext );

const goBack = useCallback( ( event ) => {
event.preventDefault();
navigateToScreen( 'account-status' );
}, [] );
const goBack = useCallback(
( event ) => {
event.preventDefault();
navigateToScreen( 'account-status' );
},
[ navigateToScreen ]
);

return (
<Modal
Expand Down
11 changes: 7 additions & 4 deletions settings/src/components/screen-link.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ export default function ScreenLink( { screen, anchorText, buttonStyle = false, a
classes.push( 'is-secondary' );
}

const onClick = useCallback( ( event ) => {
event.preventDefault();
navigateToScreen( screen );
}, [] );
const onClick = useCallback(
( event ) => {
event.preventDefault();
navigateToScreen( screen );
},
[ navigateToScreen ]
);

return (
<a
Expand Down
42 changes: 42 additions & 0 deletions settings/src/components/screen-navigation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* WordPress dependencies
*/
import { Icon, chevronLeft } from '@wordpress/icons';
import { Card, CardHeader, CardBody } from '@wordpress/components';

/**
* Internal dependencies
*/
import ScreenLink from './screen-link';

/**
* @param props
* @param props.children
* @param props.screen
*/
const ScreenNavigation = ( { screen, children } ) => (
<Card>
<CardHeader className="wporg-2fa__navigation" size="xSmall">
<ScreenLink
screen="account-status"
ariaLabel="Back to the account status page"
anchorText={
<>
<Icon icon={ chevronLeft } />
Back
</>
}
/>

<h3>
{ screen
.replace( '-', ' ' )
.replace( 'totp', 'Two-Factor Authentication' )
.replace( 'webauthn', 'Two-Factor Security Key' ) }
</h3>
</CardHeader>
<CardBody className={ 'wporg-2fa__' + screen }>{ children }</CardBody>
</Card>
);

export default ScreenNavigation;
22 changes: 22 additions & 0 deletions settings/src/components/screen-navigation.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.wporg-2fa__navigation {
padding: 24px 0 !important; /* Override Gutenberg auto-generated. */
justify-content: center !important;
position: relative;

a {
display: flex;
align-items: center;
position: absolute;
left: 24px;
}

svg {
fill: #4ca6cf;
}

h3 {
margin: unset;
text-transform: capitalize;
}

}
2 changes: 1 addition & 1 deletion settings/src/components/totp.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { RawHTML, useCallback, useContext, useEffect, useRef, useState } from '@
*/
import ScreenLink from './screen-link';
import AutoTabbingInput from './auto-tabbing-input';
import { refreshRecord } from '../utilities';
import { refreshRecord } from '../utilities/common';
import { GlobalContext } from '../script';

export default function TOTP() {
Expand Down
3 changes: 1 addition & 2 deletions settings/src/components/webauthn/list-keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import { Icon, cancelCircleFilled } from '@wordpress/icons';
* Internal dependencies
*/
import { GlobalContext } from '../../script';
import { refreshRecord } from '../../utilities';

import { refreshRecord } from '../../utilities/common';
/**
* Render the list of keys.
*/
Expand Down
2 changes: 1 addition & 1 deletion settings/src/components/webauthn/register-key.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Icon, check, cancelCircleFilled } from '@wordpress/icons';
* Internal dependencies
*/
import { GlobalContext } from '../../script';
import { refreshRecord } from '../../utilities';
import { refreshRecord } from '../../utilities/common';
import {
preparePublicKeyCreationOptions,
preparePublicKeyCredential,
Expand Down
2 changes: 1 addition & 1 deletion settings/src/components/webauthn/webauthn.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import apiFetch from '@wordpress/api-fetch';
* Internal dependencies
*/
import { GlobalContext } from '../../script';
import { refreshRecord } from '../../utilities';
import { refreshRecord } from '../../utilities/common';
import ListKeys from './list-keys';
import RegisterKey from './register-key';

Expand Down
21 changes: 0 additions & 21 deletions settings/src/utilities.js → settings/src/hooks/useUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,3 @@ export function useUser( userId ) {
webAuthnEnabled,
};
}

/**
* Refresh a `useEntityRecord` object from the REST API.
*
* This is necessary after an the underlying data in the database has been changed by a method other than
* `userRecord.save()`. When that happens, the `userRecord` object isn't automatically updated, and needs to be manually
* refreshed to get the latest data.
*
* todo Replace this with native method if one is added in https://github.com/WordPress/gutenberg/issues/47746.
*
* @param userRecord An userRecord object that was generated by `useEntityRecord()`.
*
* @return {Promise} A promise that resolves when the record has been refreshed.
*/
export function refreshRecord( userRecord ) {
// The fake key will be ignored by the REST API because it isn't a registered field. But the request will still
// result in the latest data being returned.
userRecord.edit( { refreshRecordFakeKey: '' } );

return userRecord.save();
}
42 changes: 9 additions & 33 deletions settings/src/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ import {
useState,
createRoot,
} from '@wordpress/element';
import { Icon, chevronLeft } from '@wordpress/icons';
import { Card, CardHeader, CardBody, Spinner } from '@wordpress/components';
import { Spinner } from '@wordpress/components';

/**
* Internal dependencies
*/
import { useUser } from './utilities';
import ScreenLink from './components/screen-link';
import { useUser } from './hooks/useUser';
import ScreenNavigation from './components/screen-navigation';
import AccountStatus from './components/account-status';
import Password from './components/password';
import EmailAddress from './components/email-address';
Expand Down Expand Up @@ -143,35 +142,12 @@ function Main( { userId } ) {
return <Spinner />;
}

const currentScreen = components[ screen ];
let screenContent = currentScreen;

if ( 'account-status' !== screen ) {
screenContent = (
<Card>
<CardHeader className="wporg-2fa__navigation" size="xSmall">
<ScreenLink
screen="account-status"
ariaLabel="Back to the account status page"
anchorText={
<>
<Icon icon={ chevronLeft } />
Back
</>
}
/>

<h3>
{ screen
.replace( '-', ' ' )
.replace( 'totp', 'Two-Factor Authentication' )
.replace( 'webauthn', 'Two-Factor Security Key' ) }
</h3>
</CardHeader>
<CardBody className={ 'wporg-2fa__' + screen }>{ currentScreen }</CardBody>
</Card>
const currentScreenComponent =
'account-status' === screen ? (
components[ screen ]
) : (
<ScreenNavigation screen={ screen }>{ components[ screen ] }</ScreenNavigation>
);
}

const isRevalidationExpired =
twoFactorRequiredScreens.includes( screen ) &&
Expand All @@ -185,7 +161,7 @@ function Main( { userId } ) {
value={ { navigateToScreen, user, setGlobalNotice, setError, error } }
>
<GlobalNotice notice={ globalNotice } setNotice={ setGlobalNotice } />
{ screenContent }
{ currentScreenComponent }
{ shouldRevalidate && <RevalidateModal /> }
</GlobalContext.Provider>
);
Expand Down
24 changes: 1 addition & 23 deletions settings/src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,29 +50,6 @@ $alert-blue: #72aee6;
flex-wrap: wrap;
}

.wporg-2fa__navigation {
padding: 24px 0 !important; /* Override Gutenberg auto-generated. */
justify-content: center !important;
position: relative;

a {
display: flex;
align-items: center;
position: absolute;
left: 24px;
}

svg {
fill: #4ca6cf;
}

h3 {
margin: unset;
text-transform: capitalize;
}

}

.wporg-2fa__token {
letter-spacing: .3em;
}
Expand Down Expand Up @@ -105,5 +82,6 @@ $alert-blue: #72aee6;
@import "components/setup-progress-bar";
@import "components/global-notice";
@import "components/screen-link";
@import "components/screen-navigation";
@import "components/auto-tabbing-input";
@import "components/revalidate-modal";
Loading

0 comments on commit 2f6c51e

Please sign in to comment.