Skip to content

Commit

Permalink
Add reusable Widget area, New badge feature.
Browse files Browse the repository at this point in the history
  • Loading branch information
benbowler committed May 20, 2024
1 parent 363402e commit 99f453b
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 2 deletions.
54 changes: 52 additions & 2 deletions assets/js/googlesitekit/widgets/components/WidgetAreaRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ import WidgetCellWrapper from './WidgetCellWrapper';
import useViewOnly from '../../../hooks/useViewOnly';
import { CORE_USER } from '../../datastore/user/constants';
import useLatestIntersection from '../../../hooks/useLatestIntersection';
import NewBadge from '../../../components/NewBadge';
import { WEEK_IN_SECONDS } from '../../../util';
import { useDispatch } from '@wordpress/data';
const { useSelect } = Data;

/**
Expand Down Expand Up @@ -95,6 +98,10 @@ export default function WidgetAreaRenderer( { slug, contextID } ) {
const widgetArea = useSelect( ( select ) =>
select( CORE_WIDGETS ).getWidgetArea( slug )
);

const { Icon, title, style, subtitle, hasNewBadge, CTA, Footer } =
widgetArea;

const widgets = useSelect( ( select ) =>
select( CORE_WIDGETS ).getWidgets( slug, {
modules: viewableModules ? viewableModules : undefined,
Expand Down Expand Up @@ -129,6 +136,47 @@ export default function WidgetAreaRenderer( { slug, contextID } ) {
} );
}, [ intersectionEntry, slug, activeContextID, contextID ] );

// NewBadge Expirable Item
const expirableBadgeSlug = `widget-area-expirable-new-badge-${ slug }`;

const hasBadgeBeenSeen = useSelect( ( select ) =>
select( CORE_USER ).hasExpirableItem( expirableBadgeSlug )
);
const isExpiredBadgeActive = useSelect( ( select ) =>
select( CORE_USER ).isExpirableItemActive( expirableBadgeSlug )
);

// Show the new badge if this widget area allows new badges, it's new badge
// has not been seen yet, or the badge has been seen and is still active.
const showNewBadge =
hasNewBadge && ( hasBadgeBeenSeen === false || isExpiredBadgeActive );

const { setExpirableItemTimers } = useDispatch( CORE_USER );

useEffect( () => {
// Wait until the selectors have resolved.
if (
hasBadgeBeenSeen !== undefined &&
isExpiredBadgeActive !== undefined
) {
// Only set the expirable item if the badge is new and the user is viewing it for the first time.
if ( hasNewBadge && ! hasBadgeBeenSeen ) {
setExpirableItemTimers( [
{
slug: expirableBadgeSlug,
expiresInSeconds: WEEK_IN_SECONDS * 4,
},
] );
}
}
}, [
hasNewBadge,
expirableBadgeSlug,
hasBadgeBeenSeen,
isExpiredBadgeActive,
setExpirableItemTimers,
] );

if ( viewableModules === undefined ) {
return null;
}
Expand Down Expand Up @@ -175,8 +223,6 @@ export default function WidgetAreaRenderer( { slug, contextID } ) {
</WidgetCellWrapper>
) );

const { Icon, title, style, subtitle, CTA, Footer } = widgetArea;

return (
<InViewProvider value={ inViewState }>
{ !! isActive && (
Expand All @@ -198,6 +244,7 @@ export default function WidgetAreaRenderer( { slug, contextID } ) {
{ title && (
<h3 className="googlesitekit-widget-area-header__title googlesitekit-heading-3">
{ title }
{ showNewBadge && <NewBadge /> }
</h3>
) }

Expand All @@ -206,6 +253,9 @@ export default function WidgetAreaRenderer( { slug, contextID } ) {
{ subtitle && (
<h4 className="googlesitekit-widget-area-header__subtitle">
{ subtitle }
{ showNewBadge && ! title && (
<NewBadge />
) }
</h4>
) }

Expand Down
4 changes: 4 additions & 0 deletions assets/js/googlesitekit/widgets/datastore/areas.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export const actions = {
* @since 1.107.0 Extended to support an optional CTA component.
* @since 1.110.0 Extended to support an optional filterActiveWidgets function.
* @since n.e.x.t Extended to make title optional and support an optional Footer component.
* @since n.e.x.t Extended to support an optional hasNewBadge parameter.
*
* @param {string} slug Widget Area's slug.
* @param {Object} settings Widget Area's settings.
Expand All @@ -91,6 +92,7 @@ export const actions = {
* @param {WPComponent} [settings.Icon] Optional. React component to render icon for this widget area.
* @param {string} [settings.style] Optional. Widget area style (one of "boxes", "composite"). Default: "boxes".
* @param {number} [settings.priority] Optional. Priority for this widget area. Default: 10.
* @param {boolean} [settings.hasNewBadge] Optional. Whether this widget area should display a new badge.
* @param {WPComponent} [settings.CTA] Optional. React component used as CTA appearing beside the subtitle.
* @param {WPComponent} [settings.Footer] Optional. React component used as footer for the widget area.
* @param {Function} [settings.filterActiveWidgets] Optional. Function used to filter active widgets.
Expand All @@ -104,6 +106,7 @@ export const actions = {
title,
subtitle,
Icon,
hasNewBadge = false,
CTA,
Footer,
filterActiveWidgets,
Expand All @@ -124,6 +127,7 @@ export const actions = {
title,
subtitle,
Icon,
hasNewBadge,
CTA,
Footer,
filterActiveWidgets,
Expand Down
2 changes: 2 additions & 0 deletions assets/js/googlesitekit/widgets/register-defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export function registerDefaults( widgetsAPI ) {
'Track your site’s traffic over time',
'google-site-kit'
),
hasNewBadge: true, // TODO: remove this as this is only for testing the new badge with a title.
style: WIDGET_AREA_STYLES.BOXES,
priority: 1,
},
Expand All @@ -149,6 +150,7 @@ export function registerDefaults( widgetsAPI ) {
'Understand how different visitor groups interact with your site',
'google-site-kit'
),
hasNewBadge: true,
style: WIDGET_AREA_STYLES.BOXES,
priority: 2,
Footer: AudienceAreaFooter,
Expand Down

0 comments on commit 99f453b

Please sign in to comment.