import apiFetch from '@wordpress/api-fetch'; import {glue} from './glue'; /** * Generic API handler for onboarding actions * @param {string} action - The action to perform * @param {Object} data - Data to send with the request * @returns {Promise<*>} */ export const handleRequest = async( args ) => { const {method, path, data} = args; if ( method === 'GET' ) { args.path = `${args.path}${glue(args.path)}${buildQueryString( args.data )}`; delete args.data; } return apiFetch( args ) .then( ( response ) => { if ( ! response.request_success ) { throw new Error( 'invalid data error' ); } if ( response.code ) { throw new Error( response.message ); } delete response.request_success; return response; }) .catch( ( error ) => { // If REST API fails, try AJAX request return ajaxRequest( method, path, data ).catch( () => { // If AJAX also fails, generate error console.log( error.message, args.path ); throw error; }); }); } export const updateAction = async( data = {}, action ) => { const onboardingData = window[`teamupdraft_onboarding`] || {} const endpointUrl = onboardingData.prefix + '/v1/onboarding/do_action/'+action; data.nonce = onboardingData.nonce; const path = endpointUrl; const method = 'POST'; let args = { path, method, data, }; return await handleRequest(args); } const siteUrl = ( ) => { const onboardingData = window[`teamupdraft_onboarding`] || {} let url = onboardingData.admin_ajax_url; if ( 'https:' === window.location.protocol && -1 === url.indexOf( 'https://' ) ) { return url.replace( 'http://', 'https://' ); } return url; }; const ajaxRequest = async( method, path, requestData = null ) => { //if requestData is an object, convert it to an array const queryString = buildQueryString( requestData ); //add path to request data requestData.path = path; const url = 'GET' === method ? `${siteUrl()}&rest_action=${path.replace( '?', '&' )}&`+queryString : siteUrl(); const options = { method, headers: { 'Content-Type': 'application/json; charset=UTF-8' } }; if ( 'POST' === method ) { options.body = JSON.stringify({ path, data: requestData } ); } try { const response = await fetch( url, options ); if ( ! response.ok ) { return Promise.reject( new Error( 'AJAX request failed' ) ); } const responseData = await response.json(); if ( ! responseData.data || ! Object.prototype.hasOwnProperty.call( responseData.data, 'request_success' ) ) { return Promise.reject( new Error( 'AJAX request failed' ) ); } delete responseData.data.request_success; // return promise with the data object return Promise.resolve( responseData.data ); } catch ( error ) { return Promise.reject( new Error( 'AJAX request failed' ) ); } } /** * Build query string from object of parameters * @param {Object} params * @returns {string} */ const buildQueryString = ( params ) => { return Object.keys( params ) .filter( ( key ) => params[key] !== undefined && null !== params[key]) .map( ( key ) => { const value = serializeValue( params[key]); if ( Array.isArray( value ) ) { // Handle arrays by using the PHP array syntax: metrics[]=value1&metrics[]=value2 return value .map( ( v ) => `${encodeURIComponent( key )}[]=${encodeURIComponent( v )}` ) .join( '&' ); } return `${encodeURIComponent( key )}=${encodeURIComponent( value )}`; }) .join( '&' ); }; /** * Serialize value for URL parameters, handling arrays and objects * @param {*} value - Value to serialize * @returns {string} Serialized value */ const serializeValue = ( value ) => { if ( Array.isArray( value ) ) { // For arrays, add [] to the key and keep values separate return value; } if ( 'object' === typeof value && null !== value ) { return JSON.stringify( value ); } return value; }; /** * Send Admin Ajax for default wordpress ajax requests * @param {Object} params * @returns {Promise<*>} */ export const adminAjaxRequest = async(requestData = null ) => { const method = 'POST'; const fullUrl = new URL(siteUrl()); fullUrl.search = ""; // remove query parameters const url = fullUrl.toString(); // Convert object to x-www-form-urlencoded string const formBody = new URLSearchParams(requestData).toString(); const options = { method, headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, body: formBody }; try { const response = await fetch( url, options ); if ( !response.ok ) { return Promise.reject( new Error( 'AJAX request failed' ) ); } const responseData = await response.json(); // return promise with the data object return Promise.resolve( responseData ); } catch ( error ) { return Promise.reject( new Error( 'AJAX request failed' ) ); } }