Skip to content

Commit

Permalink
Merge branch 'develop' into new/#6966-ad-blocking-recovery-onboarding.
Browse files Browse the repository at this point in the history
  • Loading branch information
nfmohit committed Jun 22, 2023
2 parents 4221b6a + 7133b0d commit 7512ee4
Show file tree
Hide file tree
Showing 58 changed files with 1,701 additions and 634 deletions.
14 changes: 0 additions & 14 deletions .storybook/storybook-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,6 @@ module.exports = [
},
},
},
{
id: 'global--modal-dialog',
kind: 'Global',
name: 'Modal Dialog',
story: 'Modal Dialog',
parameters: {
fileName: './stories/modal-dialog.stories.js',
options: {
hierarchyRootSeparator: '|',
hierarchySeparator: {},
delay: 1000,
},
},
},
{
id: 'adsense-module-components-module-overview-widget--loaded',
kind: 'AdSense Module',
Expand Down
2 changes: 1 addition & 1 deletion assets/js/components/KeyMetrics/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const { useSelect } = Data;
/**
* Returns a Higher-Order Component to render wrapped components when the Key Metrics widget is visible.
*
* @since n.e.x.t
* @since 1.103.0
*
* @return {Function} Enhancing function.
*/
Expand Down
147 changes: 147 additions & 0 deletions assets/js/components/ModalDialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/**
* ModalDialog component.
*
* Site Kit by Google, Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* External dependencies
*/
import PropTypes from 'prop-types';

/**
* WordPress dependencies
*/
import { useInstanceId } from '@wordpress/compose';
import { createInterpolateElement } from '@wordpress/element';
import { sprintf, __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import {
SpinnerButton,
Dialog,
DialogTitle,
DialogContent,
DialogFooter,
} from 'googlesitekit-components';
import Link from './Link';

const ModalDialog = ( {
dialogActive,
handleDialog,
title,
provides,
handleConfirm,
subtitle,
confirmButton,
dependentModules,
danger,
inProgress = false,
} ) => {
const instanceID = useInstanceId( ModalDialog );
const describedByID = `googlesitekit-dialog-description-${ instanceID }`;
const hasProvides = !! ( provides && provides.length );

return (
<Dialog
open={ dialogActive }
aria-describedby={ hasProvides ? describedByID : undefined }
tabIndex="-1"
>
<DialogTitle>{ title }</DialogTitle>
{
// Ensure we don't render anything at all if subtitle is falsy, as Dialog expects all its children to be elements and a falsy value will result in an error.
subtitle ? <p className="mdc-dialog__lead">{ subtitle }</p> : []
}
<DialogContent>
{ hasProvides && (
<section
id={ describedByID }
className="mdc-dialog__provides"
>
<ul className="mdc-list mdc-list--underlined mdc-list--non-interactive">
{ provides.map( ( attribute ) => (
<li className="mdc-list-item" key={ attribute }>
<span className="mdc-list-item__text">
{ attribute }
</span>
</li>
) ) }
</ul>
</section>
) }
{ dependentModules && (
<p className="mdc-dialog__dependencies">
{ createInterpolateElement(
sprintf(
/* translators: %s is replaced with the dependent modules. */
__(
'<strong>Note:</strong> %s',
'google-site-kit'
),
dependentModules
),
{
strong: <strong />,
}
) }
</p>
) }
</DialogContent>
<DialogFooter>
<SpinnerButton
onClick={ handleConfirm }
danger={ danger }
disabled={ inProgress }
isSaving={ inProgress }
>
{ confirmButton || __( 'Disconnect', 'google-site-kit' ) }
</SpinnerButton>
<Link
className="googlesitekit-margin-left-auto mdc-dialog__cancel-button"
onClick={ handleDialog }
disabled={ inProgress }
>
{ __( 'Cancel', 'google-site-kit' ) }
</Link>
</DialogFooter>
</Dialog>
);
};

ModalDialog.displayName = 'Dialog';

ModalDialog.propTypes = {
dialogActive: PropTypes.bool,
handleDialog: PropTypes.func,
handleConfirm: PropTypes.func.isRequired,
title: PropTypes.string,
description: PropTypes.string,
confirmButton: PropTypes.string,
danger: PropTypes.bool,
};

ModalDialog.defaultProps = {
dialogActive: false,
handleDialog: null,
title: null,
description: null,
confirmButton: null,
danger: false,
};

export default ModalDialog;
51 changes: 51 additions & 0 deletions assets/js/components/ModalDialog.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* ModalDialog Component Stories.
*
* Site Kit by Google, Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Internal dependencies
*/
import ModalDialog from './ModalDialog';

const Template = () => (
<ModalDialog
dialogActive
title="Modal Dialog Title"
subtitle="Modal Dialog Subtitle"
provides={ [
'Audience overview',
'Top pages',
'Top acquisition channels',
] }
handleConfirm={ global.console.log.bind(
null,
'Dialog::handleConfirm'
) }
danger
/>
);

export const Default = Template.bind( {} );
Default.storyName = 'Default';
Default.scenario = {
label: 'Global/ModalDialog',
};

export default {
title: 'Global/Modal Dialog',
component: ModalDialog,
};
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { useEffect, useCallback } from '@wordpress/element';
* Internal dependencies
*/
import Data from 'googlesitekit-data';
import { Dialog } from 'googlesitekit-components';
import ModalDialog from '../ModalDialog';
import { CORE_USER } from '../../googlesitekit/datastore/user/constants';
import { CORE_LOCATION } from '../../googlesitekit/datastore/location/constants';
import { snapshotAllStores } from '../../googlesitekit/data/create-snapshot-store';
Expand Down Expand Up @@ -107,7 +107,7 @@ const AuthenticatedPermissionsModal = () => {

return (
<Portal>
<Dialog
<ModalDialog
title={ __(
'Additional Permissions Required',
'google-site-kit'
Expand Down
4 changes: 2 additions & 2 deletions assets/js/components/ResetButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { useDebounce } from '../hooks/useDebounce';
* Internal dependencies
*/
import Data from 'googlesitekit-data';
import { Dialog } from 'googlesitekit-components';
import ModalDialog from './ModalDialog';
import { clearCache } from '../googlesitekit/api/cache';
import Portal from './Portal';
import Link from './Link';
Expand Down Expand Up @@ -122,7 +122,7 @@ function ResetButton( { children } ) {
{ children || __( 'Reset Site Kit', 'google-site-kit' ) }
</Link>
<Portal>
<Dialog
<ModalDialog
dialogActive={ dialogActive }
handleConfirm={ handleUnlinkConfirm }
handleDialog={ toggleDialogActive }
Expand Down
43 changes: 37 additions & 6 deletions assets/js/components/ResetButton.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
fireEvent,
act,
provideSiteInfo,
waitFor,
} from '../../../tests/js/test-utils';
import { CORE_SITE } from '../googlesitekit/datastore/site/constants';
import ResetButton from './ResetButton';
Expand Down Expand Up @@ -80,17 +81,23 @@ describe( 'ResetButton', () => {

describe( 'after click', () => {
let container;
beforeEach( () => {
beforeEach( async () => {
container = render( <ResetButton />, { registry } ).container;
fireEvent.click(
container.querySelector( '.googlesitekit-reset-button' )
);

await waitFor( () => {
expect(
document.querySelector( '.mdc-dialog--open' )
).toBeInTheDocument();
} );
} );

it( 'should open the dialog', () => {
expect(
document.querySelector( '.mdc-dialog--open' )
).toBeInTheDocument();
expect( document.querySelector( '.mdc-dialog' ) ).toHaveClass(
'mdc-dialog--open'
);
} );

it( 'should show reset and cancel buttons', () => {
Expand All @@ -106,22 +113,46 @@ describe( 'ResetButton', () => {
).toBeInTheDocument();
} );

it( 'should close the modal on clicking cancel', () => {
it( 'should close the modal on clicking cancel', async () => {
fireEvent.click(
document.querySelector(
'.mdc-dialog--open .mdc-dialog__cancel-button'
)
);

await waitFor( () => {
expect(
document.querySelector( '.mdc-dialog--closing' )
).not.toBeInTheDocument();
} );

expect(
document.querySelector( '.mdc-dialog--open' )
).not.toBeInTheDocument();

// Verify that none of .mdc-dialog--opening, .mdc-dialog--open or .mdc-dialog--closing are applied to the .mdc-dialog element.
expect(
document.querySelector( '.mdc-dialog' ).classList.length
).toBe( 1 );
} );

it( 'should close the modal on pressing escape key', () => {
it( 'should close the modal on pressing escape key', async () => {
fireEvent.keyUp( global, { keyCode: ESCAPE } );

await waitFor( () => {
expect(
document.querySelector( '.mdc-dialog--closing' )
).not.toBeInTheDocument();
} );

expect(
document.querySelector( '.mdc-dialog--open' )
).not.toBeInTheDocument();

// Verify that none of .mdc-dialog--opening, .mdc-dialog--open or .mdc-dialog--closing are applied to the .mdc-dialog element.
expect(
document.querySelector( '.mdc-dialog' ).classList.length
).toBe( 1 );
} );

it( 'should reset the plugin, delete local and session storage', async () => {
Expand Down
5 changes: 3 additions & 2 deletions assets/js/components/UserMenu/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ import { ESCAPE, TAB } from '@wordpress/keycodes';
* Internal dependencies
*/
import Data from 'googlesitekit-data';
import { Button, Dialog, Menu } from 'googlesitekit-components';
import { Button, Menu } from 'googlesitekit-components';
import ModalDialog from '../ModalDialog';
import { trackEvent } from '../../util';
import { clearCache } from '../../googlesitekit/api/cache';
import Portal from '../Portal';
Expand Down Expand Up @@ -276,7 +277,7 @@ export default function UserMenu() {
</Menu>
</div>
<Portal>
<Dialog
<ModalDialog
dialogActive={ dialogActive }
handleConfirm={ handleUnlinkConfirm }
handleDialog={ handleDialog }
Expand Down
Loading

0 comments on commit 7512ee4

Please sign in to comment.