d36bb954d1
Baseline before backporting wp-data-optimizer v3.0.1-v3.4.6. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
247 lines
5.8 KiB
JavaScript
247 lines
5.8 KiB
JavaScript
/**
|
|
* WP Data Optimizer — Admin JS (native fetch, no jQuery)
|
|
*
|
|
* @package WP_Data_Optimizer
|
|
*/
|
|
|
|
( function () {
|
|
'use strict';
|
|
|
|
var WPDO = window.wpdoAdmin || {};
|
|
var i18n = WPDO.i18n || {};
|
|
|
|
document.addEventListener(
|
|
'DOMContentLoaded',
|
|
function () {
|
|
bindFlushCacheButtons();
|
|
bindStatusRefresh();
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Announce a message via the shared aria-live region.
|
|
* Falls back to creating the region on first call.
|
|
*/
|
|
function announce( message ) {
|
|
var region = document.getElementById( 'wpdo-aria-live' );
|
|
if ( ! region ) {
|
|
region = document.createElement( 'div' );
|
|
region.id = 'wpdo-aria-live';
|
|
region.className = 'wpdo-sr-only';
|
|
region.setAttribute( 'role', 'status' );
|
|
region.setAttribute( 'aria-live', 'polite' );
|
|
region.setAttribute( 'aria-atomic', 'true' );
|
|
document.body.appendChild( region );
|
|
}
|
|
region.textContent = '';
|
|
setTimeout(
|
|
function () {
|
|
region.textContent = message; },
|
|
50
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Render an inline admin notice at the top of .wpdo-wrap.
|
|
* Dismissable by user. Replaces legacy alert() for errors.
|
|
*/
|
|
function showNotice( message, type ) {
|
|
type = type || 'error';
|
|
var wrap = document.querySelector( '.wpdo-wrap' );
|
|
if ( ! wrap ) {
|
|
return;
|
|
}
|
|
|
|
var notice = document.createElement( 'div' );
|
|
notice.className = 'notice notice-' + type + ' is-dismissible';
|
|
notice.setAttribute( 'role', type === 'error' ? 'alert' : 'status' );
|
|
|
|
var p = document.createElement( 'p' );
|
|
p.textContent = message;
|
|
notice.appendChild( p );
|
|
|
|
var dismiss = document.createElement( 'button' );
|
|
dismiss.type = 'button';
|
|
dismiss.className = 'notice-dismiss';
|
|
dismiss.setAttribute( 'aria-label', i18n.dismiss || 'Dismiss' );
|
|
dismiss.addEventListener(
|
|
'click',
|
|
function () {
|
|
notice.remove();
|
|
}
|
|
);
|
|
notice.appendChild( dismiss );
|
|
|
|
// Insert after the H1 so it appears at the top of the content area.
|
|
var h1 = wrap.querySelector( 'h1' );
|
|
if ( h1 && h1.nextSibling ) {
|
|
wrap.insertBefore( notice, h1.nextSibling );
|
|
} else {
|
|
wrap.prepend( notice );
|
|
}
|
|
|
|
announce( message );
|
|
}
|
|
|
|
/**
|
|
* POST to admin-ajax.php using native fetch + FormData.
|
|
* Returns a Promise resolving to the parsed JSON response.
|
|
*/
|
|
function wpdoAjax( actionType, data ) {
|
|
var body = new FormData();
|
|
body.append( 'action', 'wpdo_admin_action' );
|
|
body.append( 'nonce', WPDO.nonce || '' );
|
|
body.append( 'action_type', actionType );
|
|
Object.keys( data || {} ).forEach(
|
|
function ( key ) {
|
|
body.append( key, data[ key ] );
|
|
}
|
|
);
|
|
|
|
return fetch(
|
|
WPDO.ajaxUrl,
|
|
{
|
|
method: 'POST',
|
|
credentials: 'same-origin',
|
|
body: body,
|
|
}
|
|
)
|
|
.then(
|
|
function ( res ) {
|
|
if ( ! res.ok ) {
|
|
throw new Error( 'HTTP ' + res.status );
|
|
}
|
|
return res.json();
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Flush cache button handler — delegated click listener.
|
|
*/
|
|
function bindFlushCacheButtons() {
|
|
document.addEventListener(
|
|
'click',
|
|
function ( e ) {
|
|
var btn = e.target.closest( '.wpdo-flush-cache' );
|
|
if ( ! btn ) {
|
|
return;
|
|
}
|
|
e.preventDefault();
|
|
|
|
var postType = btn.getAttribute( 'data-post-type' );
|
|
if ( ! postType ) {
|
|
return;
|
|
}
|
|
|
|
var originalLabel = btn.textContent;
|
|
btn.disabled = true;
|
|
btn.textContent = i18n.flushing || 'Flushing…';
|
|
announce( btn.textContent );
|
|
|
|
wpdoAjax( 'flush_cache', { post_type: postType } )
|
|
.then(
|
|
function ( response ) {
|
|
if ( response && response.success ) {
|
|
btn.textContent = i18n.flushed || 'Flushed!';
|
|
announce( btn.textContent );
|
|
setTimeout(
|
|
function () {
|
|
btn.disabled = false;
|
|
btn.textContent = i18n.flushLabel || originalLabel;
|
|
},
|
|
2000
|
|
);
|
|
} else {
|
|
btn.disabled = false;
|
|
btn.textContent = i18n.flushLabel || originalLabel;
|
|
var msg = ( response && response.data ) ? String( response.data ) : ( i18n.error || 'Unknown error' );
|
|
showNotice( msg, 'error' );
|
|
}
|
|
}
|
|
)
|
|
.catch(
|
|
function () {
|
|
btn.disabled = false;
|
|
btn.textContent = i18n.flushLabel || originalLabel;
|
|
showNotice( i18n.error || 'Request failed.', 'error' );
|
|
}
|
|
);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Auto-refresh module status on the Dashboard tab (every 30s).
|
|
*/
|
|
function bindStatusRefresh() {
|
|
var isDashboard = document.querySelector( '.wpdo-wrap' )
|
|
&& window.location.search.indexOf( 'tab=dashboard' ) !== -1;
|
|
if ( ! isDashboard ) {
|
|
return;
|
|
}
|
|
|
|
var timer = setInterval(
|
|
function () {
|
|
if ( ! document.hidden ) {
|
|
refreshStatus();
|
|
}
|
|
},
|
|
30000
|
|
);
|
|
|
|
window.addEventListener(
|
|
'beforeunload',
|
|
function () {
|
|
clearInterval( timer );
|
|
}
|
|
);
|
|
}
|
|
|
|
function refreshStatus() {
|
|
wpdoAjax( 'module_status', {} )
|
|
.then(
|
|
function ( response ) {
|
|
if ( ! response || ! response.success || ! response.data ) {
|
|
return;
|
|
}
|
|
var data = response.data;
|
|
var changed = 0;
|
|
var changedSummaries = [];
|
|
|
|
document.querySelectorAll( '.wpdo-state' ).forEach(
|
|
function ( el ) {
|
|
var row = el.closest( 'tr' );
|
|
var codeEl = row ? row.querySelector( 'code' ) : null;
|
|
if ( ! codeEl ) {
|
|
return;
|
|
}
|
|
var module = codeEl.textContent;
|
|
if ( ! module || ! ( module in data ) ) {
|
|
return;
|
|
}
|
|
var newState = data[ module ];
|
|
if ( el.textContent === newState ) {
|
|
return;
|
|
}
|
|
el.textContent = newState;
|
|
el.className = 'wpdo-state wpdo-state-' + newState;
|
|
changed++;
|
|
changedSummaries.push( module + ' → ' + newState );
|
|
}
|
|
);
|
|
|
|
if ( changed > 0 ) {
|
|
announce( changedSummaries.join( '、' ) );
|
|
}
|
|
}
|
|
)
|
|
.catch(
|
|
function () {
|
|
// Fail silently on polling — user will see the stale state; not worth a notice.
|
|
}
|
|
);
|
|
}
|
|
|
|
} )();
|