@@ -11,21 +11,73 @@ import domReady from '@wordpress/dom-ready';
1111import './style.css' ;
1212
1313/**
14- * Updates a menu item with its count.
14+ * Get session storage key for storing the previously-fetched count.
1515 *
16- * If the count is not a number or is `0`, the element that contains the count is instead removed (as it would be no longer relevant).
16+ * @param {string } itemId Menu item ID.
17+ * @return {string } Session storage key.
18+ */
19+ function getSessionStorageKey ( itemId ) {
20+ return `${ itemId } -last-count` ;
21+ }
22+
23+ /**
24+ * Sets the loading state on a menu item.
25+ *
26+ * @param {string } itemId Menu item ID.
27+ */
28+ function setMenuItemIsLoading ( itemId ) {
29+ const itemEl = document . getElementById ( itemId ) ;
30+
31+ if ( ! itemEl || itemEl . querySelector ( '.amp-count-loading' ) ) {
32+ return ;
33+ }
34+
35+ // Add a loading spinner if we haven't obtained the count before or the last count was not zero.
36+ const lastCount = sessionStorage . getItem ( getSessionStorageKey ( itemId ) ) ;
37+ if ( ! lastCount || '0' !== lastCount ) {
38+ const loadingEl = document . createElement ( 'span' ) ;
39+ loadingEl . classList . add ( 'amp-count-loading' ) ;
40+ itemEl . append ( loadingEl ) ;
41+
42+ itemEl . classList . add ( 'awaiting-mod' ) ;
43+ }
44+ }
45+
46+ /**
47+ * Sets a menu item count value.
48+ *
49+ * If the count is not a number or is `0`, the element that contains the count is instead removed (as it would be no
50+ * longer relevant).
1751 *
18- * @param {HTMLElement } itemEl Menu item element .
19- * @param {number } count Count to set.
52+ * @param {string } itemId Menu item ID .
53+ * @param {number } count Count to set.
2054 */
21- function updateMenuItem ( itemEl , count ) {
55+ function setMenuItemCountValue ( itemId , count ) {
56+ const itemEl = document . getElementById ( itemId ) ;
57+
58+ if ( ! itemEl ) {
59+ return ;
60+ }
61+
2262 if ( isNaN ( count ) || count === 0 ) {
2363 itemEl . parentNode . removeChild ( itemEl ) ;
64+ sessionStorage . setItem ( getSessionStorageKey ( itemId ) , '0' ) ;
2465 } else {
25- itemEl . textContent = count . toLocaleString ( ) ;
66+ const text = count . toLocaleString ( ) ;
67+ itemEl . textContent = text ;
68+ itemEl . classList . add ( 'awaiting-mod' ) ; // In case it wasn't set in setMenuItemIsLoading().
69+ sessionStorage . setItem ( getSessionStorageKey ( itemId ) , text ) ;
2670 }
2771}
2872
73+ /**
74+ * Initializes the 'Validated URLs' and 'Error Index' menu items.
75+ */
76+ function initializeMenuItemCounts ( ) {
77+ setMenuItemIsLoading ( 'amp-new-error-index-count' ) ;
78+ setMenuItemIsLoading ( 'amp-new-validation-url-count' ) ;
79+ }
80+
2981/**
3082 * Updates the 'Validated URLs' and 'Error Index' menu items with their respective unreviewed count.
3183 *
@@ -36,15 +88,23 @@ function updateMenuItem( itemEl, count ) {
3688function updateMenuItemCounts ( counts ) {
3789 const { validated_urls : newValidatedUrlCount , errors : newErrorCount } = counts ;
3890
39- const errorCountEl = document . getElementById ( 'new-error-index-count' ) ;
40- if ( errorCountEl ) {
41- updateMenuItem ( errorCountEl , newErrorCount ) ;
42- }
91+ setMenuItemCountValue ( 'amp-new-error-index-count' , newErrorCount ) ;
92+ setMenuItemCountValue ( 'amp-new-validation-url-count' , newValidatedUrlCount ) ;
93+ }
4394
44- const validatedUrlsCountEl = document . getElementById ( 'new-validation-url-count' ) ;
45- if ( validatedUrlsCountEl ) {
46- updateMenuItem ( validatedUrlsCountEl , newValidatedUrlCount ) ;
47- }
95+ /**
96+ * Requests validation counts.
97+ */
98+ function fetchValidationCounts ( ) {
99+ apiFetch ( { path : '/amp/v1/unreviewed-validation-counts' } ) . then ( ( counts ) => {
100+ updateMenuItemCounts ( counts ) ;
101+ } ) . catch ( ( error ) => {
102+ updateMenuItemCounts ( { validated_urls : 0 , errors : 0 } ) ;
103+
104+ const message = error ?. message || __ ( 'An unknown error occurred while retrieving the validation counts' , 'amp' ) ;
105+ // eslint-disable-next-line no-console
106+ console . error ( `[AMP Plugin] ${ message } ` ) ;
107+ } ) ;
48108}
49109
50110/**
@@ -68,15 +128,7 @@ function createObserver( root ) {
68128
69129 observer . unobserve ( target ) ;
70130
71- apiFetch ( { path : '/amp/v1/unreviewed-validation-counts' } ) . then ( ( counts ) => {
72- updateMenuItemCounts ( counts ) ;
73- } ) . catch ( ( error ) => {
74- updateMenuItemCounts ( { validated_urls : 0 , errors : 0 } ) ;
75-
76- const message = error ?. message || __ ( 'An unknown error occurred while retrieving the validation counts' , 'amp' ) ;
77- // eslint-disable-next-line no-console
78- console . error ( `[AMP Plugin] ${ message } ` ) ;
79- } ) ;
131+ fetchValidationCounts ( ) ;
80132 } , { root } ) ;
81133
82134 observer . observe ( target ) ;
@@ -90,5 +142,13 @@ domReady( () => {
90142 return ;
91143 }
92144
93- createObserver ( ampMenuItem ) ;
145+ initializeMenuItemCounts ( ) ;
146+
147+ // If the AMP submenu is opened, fetch validation counts as soon as possible. Thanks to the preload middleware for
148+ // `wp.apiFetch`, the validation count data should be available right away, so no actual HTTP request will be made.
149+ if ( ampMenuItem . classList . contains ( 'wp-menu-open' ) ) {
150+ fetchValidationCounts ( ) ;
151+ } else {
152+ createObserver ( ampMenuItem ) ;
153+ }
94154} ) ;
0 commit comments