diff --git a/docs/designers-developers/developers/data/data-core-nux.md b/docs/designers-developers/developers/data/data-core-nux.md index e937601ec864b6..66921755e5f074 100644 --- a/docs/designers-developers/developers/data/data-core-nux.md +++ b/docs/designers-developers/developers/data/data-core-nux.md @@ -32,6 +32,18 @@ _Returns_ - `?NUX.GuideInfo`: Information about the associated guide. +# **hasDismissedAnyTips** + +Returns whether or not any tips have been dismissed. + +_Parameters_ + +- _state_ `Object`: Global application state. + +_Returns_ + +- `boolean`: Whether any tips have been dismissed. + # **isTipVisible** Determines whether or not the given tip is showing. Tips are hidden if they diff --git a/packages/nux/src/components/inline-tip/index.js b/packages/nux/src/components/inline-tip/index.js index de1e8f4b05b9fe..35554ab9b73cad 100644 --- a/packages/nux/src/components/inline-tip/index.js +++ b/packages/nux/src/components/inline-tip/index.js @@ -15,21 +15,31 @@ import { __ } from '@wordpress/i18n'; export function InlineTip( { children, className, + hasDismissedAnyTips, isTipVisible, onDisableTips, onDismissTip, } ) { const [ isConfirmationVisible, setIsConfirmationVisible ] = useState( false ); - const openConfirmation = () => setIsConfirmationVisible( true ); - const closeConfirmation = () => setIsConfirmationVisible( false ); + const dismissNotice = () => { + if ( hasDismissedAnyTips ) { + onDismissTip(); + } else { + setIsConfirmationVisible( true ); + } + }; + + const closeConfirmation = () => { + setIsConfirmationVisible( false ); + }; - const dismissTip = () => { + const dismissConfirmation = () => { onDismissTip(); closeConfirmation(); }; - const disableTips = () => { + const acceptConfirmation = () => { onDisableTips(); closeConfirmation(); }; @@ -39,7 +49,7 @@ export function InlineTip( { { isTipVisible && ( { children } @@ -53,10 +63,10 @@ export function InlineTip( { > { __( 'Would you like to disable tips like these in the future?' ) }
- -
@@ -67,9 +77,13 @@ export function InlineTip( { } export default compose( - withSelect( ( select, { tipId } ) => ( { - isTipVisible: select( 'core/nux' ).isTipVisible( tipId ), - } ) ), + withSelect( ( select, { tipId } ) => { + const { isTipVisible, hasDismissedAnyTips } = select( 'core/nux' ); + return { + isTipVisible: isTipVisible( tipId ), + hasDismissedAnyTips: hasDismissedAnyTips(), + }; + } ), withDispatch( ( dispatch, { tipId } ) => { const { disableTips, dismissTip } = dispatch( 'core/nux' ); return { diff --git a/packages/nux/src/components/inline-tip/test/index.js b/packages/nux/src/components/inline-tip/test/index.js index 8f9f5c3c4c7279..0f7c2eb5386705 100644 --- a/packages/nux/src/components/inline-tip/test/index.js +++ b/packages/nux/src/components/inline-tip/test/index.js @@ -11,7 +11,7 @@ import { InlineTip } from '../'; describe( 'InlineTip', () => { it( 'should not render anything if invisible', () => { const wrapper = shallow( - + It looks like you’re writing a letter. Would you like help? ); @@ -20,17 +20,28 @@ describe( 'InlineTip', () => { it( 'should render correctly', () => { const wrapper = shallow( - + It looks like you’re writing a letter. Would you like help? ); expect( wrapper ).toMatchSnapshot(); } ); + it( 'calls `onDismissTip` when the tip is dismissed and a tip has already been dismissed', () => { + const onDismissTip = jest.fn(); + const wrapper = mount( + + It looks like you’re writing a letter. Would you like help? + + ); + wrapper.find( 'button[aria-label="Dismiss this notice"]' ).simulate( 'click' ); + expect( onDismissTip ).toHaveBeenCalled(); + } ); + it( 'calls `onDismissTip` when the tip and confirmation are dismissed', () => { const onDismissTip = jest.fn(); const wrapper = mount( - + It looks like you’re writing a letter. Would you like help? ); @@ -42,7 +53,7 @@ describe( 'InlineTip', () => { it( 'calls `onDisableTips` when the tip is dismissed and the confirmation is accepted', () => { const onDisableTips = jest.fn(); const wrapper = mount( - + It looks like you’re writing a letter. Would you like help? ); diff --git a/packages/nux/src/store/selectors.js b/packages/nux/src/store/selectors.js index 9225bd97077eee..74a793c74c382f 100644 --- a/packages/nux/src/store/selectors.js +++ b/packages/nux/src/store/selectors.js @@ -2,7 +2,7 @@ * External dependencies */ import createSelector from 'rememo'; -import { includes, difference, keys, has } from 'lodash'; +import { includes, difference, keys, has, isEmpty } from 'lodash'; /** * An object containing information about a guide. @@ -77,3 +77,14 @@ export function isTipVisible( state, tipId ) { export function areTipsEnabled( state ) { return state.preferences.areTipsEnabled; } + +/** + * Returns whether or not any tips have been dismissed. + * + * @param {Object} state Global application state. + * + * @return {boolean} Whether any tips have been dismissed. + */ +export function hasDismissedAnyTips( state ) { + return ! isEmpty( state.preferences.dismissedTips ); +} diff --git a/packages/nux/src/store/test/selectors.js b/packages/nux/src/store/test/selectors.js index 546d052958dd5e..6a382cd37cd01f 100644 --- a/packages/nux/src/store/test/selectors.js +++ b/packages/nux/src/store/test/selectors.js @@ -1,7 +1,7 @@ /** * Internal dependencies */ -import { getAssociatedGuide, isTipVisible, areTipsEnabled } from '../selectors'; +import { getAssociatedGuide, isTipVisible, areTipsEnabled, hasDismissedAnyTips } from '../selectors'; describe( 'selectors', () => { describe( 'getAssociatedGuide', () => { @@ -145,4 +145,28 @@ describe( 'selectors', () => { expect( areTipsEnabled( state ) ).toBe( false ); } ); } ); + + describe( 'hasDismissedAnyTips', () => { + it( 'should return true if a tip has been dismissed', () => { + const state = { + guides: [], + preferences: { + dismissedTips: { + 'test/tip': true, + }, + }, + }; + expect( hasDismissedAnyTips( state ) ).toBe( true ); + } ); + + it( 'should return false if tips are disabled', () => { + const state = { + guides: [], + preferences: { + dismissedTips: {}, + }, + }; + expect( hasDismissedAnyTips( state ) ).toBe( false ); + } ); + } ); } );