Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the loading state for the Audience Tile. #9030

Merged
merged 4 commits into from
Jul 23, 2024

Conversation

benbowler
Copy link
Collaborator

@benbowler benbowler commented Jul 17, 2024

Summary

Addresses issue:

Relevant technical choices

I implemented a new loading component and scss file to prevent the AudienceTile component from getting too large.

One think I noticed while working on this ticket, is that the height of the loading tile (551px) is different to other states of the tile, such as the fully loaded data state (604px). This will cause layout shift once the loading state completes. I don't think this is a major issue, also it's hard to avoid due to the differences in height of the tiles based on partial data state etc, but wanted to raise it here.

PR Author Checklist

  • My code is tested and passes existing unit tests.
  • My code has an appropriate set of unit tests which all pass.
  • My code is backward-compatible with WordPress 5.2 and PHP 7.4.
  • My code follows the WordPress coding standards.
  • My code has proper inline documentation.
  • I have added a QA Brief on the issue linked above.
  • I have signed the Contributor License Agreement (see https://cla.developers.google.com/).

Do not alter or remove anything below. The following sections will be managed by moderators only.

Code Reviewer Checklist

  • Run the code.
  • Ensure the acceptance criteria are satisfied.
  • Reassess the implementation with the IB.
  • Ensure no unrelated changes are included.
  • Ensure CI checks pass.
  • Check Storybook where applicable.
  • Ensure there is a QA Brief.

Merge Reviewer Checklist

  • Ensure the PR has the correct target branch.
  • Double-check that the PR is okay to be merged.
  • Ensure the corresponding issue has a ZenHub release assigned.
  • Add a changelog message to the issue.

Copy link

github-actions bot commented Jul 17, 2024

Build files for 2b21f2d have been deleted.

Copy link

github-actions bot commented Jul 17, 2024

Size Change: +17.7 kB (+1.07%)

Total Size: 1.67 MB

Filename Size Change
./dist/assets/css/googlesitekit-admin-css-********************.min.css 54.8 kB -519 B (-0.94%)
./dist/assets/css/googlesitekit-adminbar-css-********************.min.css 11 kB -209 B (-1.86%)
./dist/assets/css/googlesitekit-authorize-application-css-********************.min.css 846 B +4 B (+0.48%)
./dist/assets/css/googlesitekit-wp-dashboard-css-********************.min.css 7.35 kB -118 B (-1.58%)
./dist/assets/js/30-********************.js 0 B -2.76 kB (removed) 🏆
./dist/assets/js/31-********************.js 2.76 kB +503 B (+22.32%) 🚨
./dist/assets/js/32-********************.js 2.25 kB -1.39 kB (-38.14%) 🎉
./dist/assets/js/33-********************.js 3.64 kB +2.71 kB (+289.73%) 🆘
./dist/assets/js/34-********************.js 935 B +43 B (+4.82%) 🔍
./dist/assets/js/35-********************.js 892 B -2.22 kB (-71.36%) 🏆
./dist/assets/js/analytics-advanced-tracking-********************.js 901 B +125 B (+16.11%) ⚠️
./dist/assets/js/googlesitekit-activation-********************.js 23.7 kB -87 B (-0.37%)
./dist/assets/js/googlesitekit-ad-blocking-recovery-********************.js 59.5 kB +166 B (+0.28%)
./dist/assets/js/googlesitekit-adminbar-********************.js 34.5 kB -190 B (-0.55%)
./dist/assets/js/googlesitekit-api-********************.js 10 kB -38 B (-0.38%)
./dist/assets/js/googlesitekit-components-gm2-********************.js 5.88 kB -10 B (-0.17%)
./dist/assets/js/googlesitekit-components-gm3-********************.js 10.1 kB -5 B (-0.05%)
./dist/assets/js/googlesitekit-consent-mode-********************.js 25.6 kB +2 B (+0.01%)
./dist/assets/js/googlesitekit-data-********************.js 2.35 kB -1 B (-0.04%)
./dist/assets/js/googlesitekit-datastore-forms-********************.js 9.03 kB -37 B (-0.41%)
./dist/assets/js/googlesitekit-datastore-location-********************.js 2.08 kB -1 B (-0.05%)
./dist/assets/js/googlesitekit-datastore-site-********************.js 20.4 kB +46 B (+0.23%)
./dist/assets/js/googlesitekit-datastore-ui-********************.js 9.98 kB -46 B (-0.46%)
./dist/assets/js/googlesitekit-datastore-user-********************.js 25.1 kB -4 B (-0.02%)
./dist/assets/js/googlesitekit-entity-dashboard-********************.js 77 kB -105 B (-0.14%)
./dist/assets/js/googlesitekit-events-provider-contact-form-7-********************.js 646 B +1 B (+0.16%)
./dist/assets/js/googlesitekit-events-provider-ninja-forms-********************.js 712 B -19 B (-2.6%)
./dist/assets/js/googlesitekit-events-provider-optin-monster-********************.js 675 B +1 B (+0.15%)
./dist/assets/js/googlesitekit-i18n-********************.js 3.93 kB +7 B (+0.18%)
./dist/assets/js/googlesitekit-main-dashboard-********************.js 142 kB +806 B (+0.57%)
./dist/assets/js/googlesitekit-modules-********************.js 22.1 kB -37 B (-0.17%)
./dist/assets/js/googlesitekit-modules-ads-********************.js 29.5 kB -20 B (-0.07%)
./dist/assets/js/googlesitekit-modules-adsense-********************.js 113 kB +181 B (+0.16%)
./dist/assets/js/googlesitekit-modules-analytics-4-********************.js 162 kB +1.2 kB (+0.75%)
./dist/assets/js/googlesitekit-modules-pagespeed-insights-********************.js 22.6 kB -59 B (-0.26%)
./dist/assets/js/googlesitekit-modules-reader-revenue-manager-********************.js 12.8 kB +298 B (+2.38%)
./dist/assets/js/googlesitekit-modules-search-console-********************.js 58 kB -216 B (-0.37%)
./dist/assets/js/googlesitekit-modules-tagmanager-********************.js 32 kB +81 B (+0.25%)
./dist/assets/js/googlesitekit-settings-********************.js 73.9 kB +11.1 kB (+17.65%) ⚠️
./dist/assets/js/googlesitekit-splash-********************.js 73.5 kB +622 B (+0.85%)
./dist/assets/js/googlesitekit-user-input-********************.js 48.5 kB +305 B (+0.63%)
./dist/assets/js/googlesitekit-vendor-********************.js 321 kB -92 B (-0.03%)
./dist/assets/js/googlesitekit-widgets-********************.js 78.9 kB +1.12 kB (+1.44%)
./dist/assets/js/googlesitekit-wp-dashboard-********************.js 61.3 kB -202 B (-0.33%)
./dist/assets/js/runtime-********************.js 1.3 kB -4 B (-0.31%)
./dist/assets/js/36-********************.js 3.12 kB +3.12 kB (new file) 🆕
./dist/assets/js/googlesitekit-notifications-********************.js 3.63 kB +3.63 kB (new file) 🆕
ℹ️ View Unchanged
Filename Size
./dist/assets/js/googlesitekit-events-provider-easy-digital-downloads-********************.js 624 B
./dist/assets/js/googlesitekit-events-provider-mailchimp-********************.js 630 B
./dist/assets/js/googlesitekit-events-provider-popup-maker-********************.js 634 B
./dist/assets/js/googlesitekit-events-provider-woocommerce-********************.js 657 B
./dist/assets/js/googlesitekit-events-provider-wpforms-********************.js 633 B
./dist/assets/js/googlesitekit-polyfills-********************.js 376 B

compressed-size-action

Copy link
Collaborator

@techanvil techanvil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @benbowler, nice work here so far. There are a few areas that could use an update, and I've also flagged that optional change we discussed for your consideration.

Comment on lines 27 to 33
<PreviewBlock width="100%" height="14px" />
<PreviewBlock width="100%" height="52px" />
<PreviewBlock width="100%" height="52px" />
<PreviewBlock width="100%" height="52px" />
<PreviewBlock width="100%" height="52px" />
<PreviewBlock width="100%" height="52px" />
<PreviewBlock width="100%" height="52px" />
Copy link
Collaborator

@techanvil techanvil Jul 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At present the preview blocks don't match up too well in desktop viewports:

image

In practical terms this tends to result in a layout shift as all tiles tend to be in the loading state at the same time, so the initial height is derived from the loading state.

There's also a bit of a mismatch in mobile viewports, as the top preview block no longer corresponds to the title.

image

image

[Note that we do have a bug raised for the broken mobile layout, #8930), and don't need to consider that here.]

It would be good to avoid rendering that top preview block for mobile viewports, and to make use of the breakpoint-specific width props to better match the preview blocks to the loaded state.

smallWidth,
smallHeight,
tabletWidth,
tabletHeight,
desktopWidth,
desktopHeight,

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Tom, my initial approach was to match the designs. I've updated these checking there is no layout shift on the zero data state, I could increase this to match the full data state if you think that would be better, LMK.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2024-07-22 at 13 10 14 Screenshot 2024-07-22 at 13 10 08 Screenshot 2024-07-22 at 13 02 46 Screenshot 2024-07-22 at 13 02 40 Screenshot 2024-07-22 at 12 46 17

Comment on lines 200 to 212
// Remove any configuredAudiences that are no longer available in availableAudiences.
const configuredAudiences =
select( MODULES_ANALYTICS_4 ).getConfiguredAudiences();

const newConfiguredAudiences = configuredAudiences?.filter(
( configuredAudience ) =>
availableAudiences?.some(
( { name } ) => name === configuredAudience
)
);
dispatch( MODULES_ANALYTICS_4 ).setConfiguredAudiences(
newConfiguredAudiences || []
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed on the call earlier, we should move this block that updates configuredAudiences to the syncAvailableAudiences() action, as we want to ensure the list of configured audiences is updated any time we do a sync.


const settings = {
configuredAudiences: availableAudiencesFixture.reduce(
( acc, a ) => [ ...acc, a.name ],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming this line is kept what with the requested change to maybeSyncAvailableAudiences():

Please avoid abbreviated variable names as per our naming conventions (I know we do tend to use acc so let's let that one slide, but please rename a or simply destructure name).

Suggested change
( acc, a ) => [ ...acc, a.name ],
( acc, audience ) => [ ...acc, audience.name ],

.getConfiguredAudiences()
).toEqual(
availableAudiencesSubset.reduce(
( acc, a ) => [ ...acc, a.name ],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above:

Suggested change
( acc, a ) => [ ...acc, a.name ],
( acc, audience ) => [ ...acc, audience.name ],

Copy link
Collaborator Author

@benbowler benbowler Jul 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

audience is already declared in the upper scope so I will go with destructuring.

);
} );

it( 'should not call syncAvailableAudiences if the availableAudiencesLastSyncedAt is within the last hour', async () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor typo/grammatical error:

Suggested change
it( 'should not call syncAvailableAudiences if the availableAudiencesLastSyncedAt is within the last hour', async () => {
it( 'should not call syncAvailableAudiences if the availableAudiencesLastSyncedAt setting is within the last hour', async () => {

@@ -304,6 +307,107 @@ describe( 'modules/analytics-4 audiences', () => {
} );
} );

describe( 'maybeSyncAvailableAudiences', () => {
it( 'should call syncAvailableAudiences if the availableAudiencesLastSyncedAt setting is undefined', async () => {
fetchMock.post( syncAvailableAudiencesEndpoint, {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We tend to prefer postOnce() over post() where we can use it, as it's more specific and will fail if an unexpected post occurs:

Suggested change
fetchMock.post( syncAvailableAudiencesEndpoint, {
fetchMock.postOnce( syncAvailableAudiencesEndpoint, {

} );

it( 'should call syncAvailableAudiences if the availableAudiencesLastSyncedAt is not within the last hour', async () => {
fetchMock.post( syncAvailableAudiencesEndpoint, {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above:

Suggested change
fetchMock.post( syncAvailableAudiencesEndpoint, {
fetchMock.postOnce( syncAvailableAudiencesEndpoint, {


.googlesitekit-plugin {
.googlesitekit-audience-segmentation-tile-loading {
margin: 24px 24px 28px;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use $grid-gap-phone with a media rule for desktop viewports. Please take a look at the + 4px for mobile as well, that may need adjusting.

Suggested change
margin: 24px 24px 28px;
margin: $grid-gap-phone $grid-gap-phone $grid-gap-phone + 4px;
@media (min-width: $bp-desktop) {
margin: $grid-gap-desktop $grid-gap-desktop $grid-gap-desktop + 4px;
}

margin: 12px 0;

&:first-of-type {
margin-bottom: 24px;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check to see if this should also be a responsive value using $grid-gap-phone / $grid-gap-desktop.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed on the call earlier, it would be good to address the "flickering" effect when changing the list of selected audiences and so forth, where currently the tiles disappear but should remain visible in a loading state.

By the look of it, removing the check for reportLoaded from this while condition should do the trick:

That said I haven't extensively tested it. So, if you want to give that a look and feel like including it in this PR, please do, but if you feel it might start pushing this over the estimate, what with the other changes I've requested, then let me know and we can create a separate issue for it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I implemented as above, if you can let me know how to repeat the flickering I can test more, with this change I was not seeing flickering.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @benbowler - I'm no longer seeing it either with this change. Let's merge this and keep an eye on things, hopefully it's done the trick.

Copy link
Collaborator

@techanvil techanvil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @benbowler, I've spotted one more thing.

Unfortunately the way the No Audiences Banner has been implemented is a bit at odds with the changes being introduced via this issue.

Note how the NoAudienceBannerWidget widget is only considered active when there is at least one configured audience:

Component: NoAudienceBannerWidget,
width: widgets.WIDGET_WIDTHS.FULL,
priority: 1,
wrapWidget: false,
modules: [ 'analytics-4' ],
isActive: ( select ) => {
const configuredAudiences =
select( MODULES_ANALYTICS_4 ).getConfiguredAudiences();
return configuredAudiences?.length > 0;
},

Similarly the logic in NoAudienceBannerWidget depends on configuredAudiences being populated:

const hasNoMatchingAudience =
configuredAudiences?.length &&
configuredAudiences.every(
( audience ) =>
Array.isArray( availableAudiences ) &&
! availableAudiences.includes( audience )
);
const configurableAudiences = availableAudiences?.filter(
( element ) =>
Array.isArray( configuredAudiences ) &&
! configuredAudiences.includes( element )
);
if ( hasNoMatchingAudience ) {

We're going to need to change the No Audiences Banner so there is only a dependency on configuredAudiences being set i.e. non-null rather than being populated, because we are now trimming configuredAudiences when we sync the audiences, so configuredAudiences may end up completely empty - a condition where the No Audiences Banner should be displayed, but currently won't be.

Again - this might be a bit much to fit into this issue - please let me know if you feel it can be addressed here, otherwise this would be fair game for a followup issue.

@benbowler
Copy link
Collaborator Author

Thanks @techanvil, to you final point, I believe I've addressed in this commit, I kept it clean so those changes can be reviewed and updated independently to get it right. Let me know if I missed anything here.

Copy link
Collaborator

@techanvil techanvil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @benbowler, this LGTM. Nice work!

@techanvil techanvil merged commit ef49540 into develop Jul 23, 2024
22 checks passed
@techanvil techanvil deleted the enhancement/8145-audience-tile-loading branch July 23, 2024 14:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants