How to display a .gexv file on a website using sigma.js

so maybe this is the most easy question ever, but I’m reading the documentation for days now and I still don’t have a clue.

I want to display a .gexf file stored on my server on the website that’s on that server.

I managed running a sigma.js script, but not an external file like here: https://www.sigmajs.org/storybook/?path=%2Fstory%2Fload-gexf-file–story

Maybe I just don’t know how to set the file path, but actually, I’m lost.

Thanks

WordPress assets loading. Uncaught TypeError: Failed to resolve module specifier

I hope you can help me with one, it’s drivinig me crazy 🙁

I recently splitted a giant file called admin.js into many modules, using these two WordPress functions:

So, every module is mapped by an importmap, like this:

<script type=""importmap""id=""wp-importmap"">"{
   "imports":{
      "admin_colorpicker_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_colorpicker.min.js?ver=6.8.3",
      "admin_commons_js":"/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_commons.min.js?ver=6.8.3",
      "admin_datepicker_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_datepicker.min.js?ver=6.8.3",
      "admin_editor_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_editor.min.js?ver=6.8.3",
      "admin_file_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_file.min.js?ver=6.8.3",
      "admin_flexible_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_flexible.min.js?ver=6.8.3",
      "admin_helpers_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_helpers.min.js?ver=6.8.3",
      "admin_iconpicker_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_iconpicker.min.js?ver=6.8.3",
      "admin_list_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_list.min.js?ver=6.8.3",
      "admin_misc_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_misc.min.js?ver=6.8.3",
      "admin_relational_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_relational.min.js?ver=6.8.3",
      "admin_repeater_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_repeater.min.js?ver=6.8.3",
      "admin_sortable_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_sortable.min.js?ver=6.8.3",
      "admin_woocommerce_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_woocommerce.min.js?ver=6.8.3"
   }
}"</script>

In rare cases, my clients got this error from the browser:

Uncaught TypeError: Failed to resolve module specifier "admin_commons_js". Relative references must start with either "/", "./", or "../".

There’s no way to reproduce the issue on my localend/staging enviroment.

By the way, the admin.js is called AFTER the importmap.

Can anyone explain that and how to fix it?

Thanks in advance to everyone 🙂

M

I tried to reproduce the issue on my end, no luck.

Form Submit needs to wait for any ongoing Blur fetch from a field

In my React application one of the Form fields is zipCode which On Blur will populate city and state via a ZipCode-based API fetch.

valueMapChange is a mutator of the Form state-variable map valueMapMap<string, any>().

    <TextInput id="zipCode"
               onChange={(e) => valueMapChange("zipCode", e.target.value.replace(/D/g, ""))}
               onBlur={(e) => { handleZipBlur(e.target.value) }}
               ... />

    const handleZipBlur = (value: string) => {
        fetchCityState(value); // On BLUR populate 'city' and 'state'
    }

    const fetchCityState = async (zipcode: string) => {
        //...Preliminary validation
        // API fetch
        const response = await getCityState<any>(zipcode);
        if (!response.errorMessage) {
                valueMapChange('city', response.city);
                valueMapChange('state', response.state);
        }
    }

There is also a Form Submit button that submits the form. If the user is in the Zip field and clicks Submit, sometimes there’s a race condition where it doesn’t have enough time to set the City/State into the valueMap, so the submit goes in without the City/State values.

The Submit function itself shouldn’t be async because it doesn’t require anything. It doesn’t need to specifically wait for something. But it needs to detect whether an optional OnBlur City/State fetch is currently ongoing, and if so wait for that fetch. What’s the best way to implement this?

Diffrence between extending http.Server vs. http.createServer

I want to create a custom HTTP server instance, with custom methods.

The first try was to extend http.createServer(), but this fails because I can’t access my custom methods.

const {createServer, Server} = require("http");


class Direct extends Server {

    constructor(...args){
        super(...args);
    }

    foo(){
        console.log("foo");
        return "foo";
    }

}


class Wrapper extends createServer {

    constructor(...args){
        super(...args);
    }

    foo(){
        console.log("foo");
        return "foo";
    }

}


const direct = new Direct();
const wrapper = new Wrapper();


[direct, wrapper].forEach((server, i) => {

    server.once("request", (req, res) => {
        server.foo();
        res.end(`Hello from server ${i}`);        
    });

    server.listen(9000 + i, () => {
        console.log(`Server #${i} listening on port ${9000 + i}`);
    });

});

Output:

Server #0 listening on port 9000
Server #1 listening on port 9001
foo
/tmp/server.js:39
        server.foo();
               ^

TypeError: server.foo is not a function
    at Server.<anonymous> (/tmp/server.js:39:16)
    at Object.onceWrapper (node:events:633:26)
    at Server.emit (node:events:518:28)
    at parserOnIncoming (node:_http_server:1153:12)
    at HTTPParser.parserOnHeadersComplete (node:_http_common:117:17)

Node.js v22.16.0
curl -v http://127.0.0.1:9000
curl -v http://127.0.0.1:9001

As soon as the “Wrapper” server hits a request:

TypeError: server.foo is not a function
    at Server.<anonymous> (/tmp/server.js:39:16)
    at Object.onceWrapper (node:events:633:26)
    at Server.emit (node:events:518:28)
    at parserOnIncoming (node:_http_server:1153:12)
    at HTTPParser.parserOnHeadersComplete (node:_http_common:117:17)

Node.js v22.16.0

The request to the “Direct” server/class works as expected.

What’s the difference between both extending approaches above, when both http.createServer() & http.Server return an HTTP server instance?

How to handle Chrome autoplay policy in a call center web application?

Context

I’m developing a web-based call center application where agents receive incoming calls through the browser. When a call comes in, the application needs to play a ringtone to alert the agent.

Problem

Chrome’s autoplay policy is blocking the ringtone from playing automatically when an incoming call arrives. According to Chrome’s autoplay documentation, audio can only play after a user interaction.
However, in a call center context:

  • Agents may be idle when a call arrives
  • The ringtone must play immediately without requiring the agent to click something first
    This is mission-critical functionality
  • agents cannot miss incoming calls

Questions

What is the recommended approach for implementing call ringtones in web-based telephony applications given Chrome’s autoplay restrictions?

Environment:

Chrome 120+
Vanilla JavaScript (can use modern APIs)
WebRTC for call signaling

EDIT

Why This is Different from General Autoplay Questions

I’ve read the existing questions about Chrome’s autoplay policy, including this one about Chrome 76, but my situation has specific constraints:

  1. No predictable user interaction – In a call center, calls arrive randomly when agents may be idle or working on post-call tasks. We cannot require a click “just before” each call.

  2. Mission-critical audio – Unlike media websites where autoplay is a convenience, missing a ringtone means missing a customer call, which has business consequences.

  3. Long-running sessions – Agents log in once at the start of their shift (could be 4-8 hours). I need to know if a single interaction at session start is sufficient to enable audio for the entire shift.

  4. Multiple audio sources – We need ringtones, notification sounds, and potentially call audio. Do these all count as separate autoplay contexts?

Specific question: Is there a reliable pattern for “unlocking” audio permissions at session start that will persist for hours and work across all major browsers for a telephony application?

Puppeteer/Jest test for Firebase extension times out waiting for Firestore document created by onUserCreate Cloud Function

I am testing a Chrome extension (Manifest V3) using Jest and Puppeteer. The extension uses Firebase Authentication and Firestore.

The Goal:
My test needs to register a new user, wait for a backend Cloud Function to create their profile document in Firestore, and then perform actions as that user.

The Problem:
My onUserCreate Cloud Function runs successfully when a user is registered (I have verified this manually and by checking the Firestore database – the /Users/{uid} document is created correctly).

However, my test script’s polling loop, which repeatedly calls a getUserProfile function to check for this document, consistently fails to find it and eventually times out.

Why would a client-side .get() request from within a Puppeteer test fail to find a document that was successfully created by a Cloud Function moments before? Could this be a Firestore consistency issue that is specific to a test environment, or a problem with how auth state is handled by the client SDK in this context?

I have confirmed that billing is enabled for my Google Cloud project and the project is on the Blaze plan.

I have already tried implementing a polling loop to wait for the document, as suggested in similar questions, but the test still times out.

Here is the relevant code:

  1. The Cloud Function (functions/index.js):
exports.initializeNewUser = functions.auth.user().onCreate(async (user) => {
  const db = admin.firestore();
  const settingsDoc = await db.collection("settings").doc("trustScoreRules").get();
  const initialScore = settingsDoc.exists ? settingsDoc.data().initialScoreTom : 3;
  const newUserProfile = {
    email: user.email,
    trustScore: initialScore,
    // ... other fields
  };
  return db.collection("Users").doc(user.uid).set(newUserProfile);
});
  1. The Test Script Polling Logic (tests/extension.test.js):
// This happens inside a beforeAll block
// ... after user is successfully registered and signed in ...

let userProfile = null;
for (let i = 0; i < 10; i++) {
  const response = await worker.evaluate(async () => {
    return new Promise((resolve) => {
      chrome.runtime.sendMessage(
        { type: 'getUserProfile', target: 'background' },
        (response) => { resolve(response); }
      );
    });
  });
  if (response && response.success) {
    userProfile = response.profile;
    break;
  }
  await new Promise(resolve => setTimeout(resolve, 1000));
}
if (!userProfile) {
  throw new Error("Timed out waiting for user profile to be created...");
}
  1. The Client-Side Fetch Logic (offscreen.js):
case 'getUserProfile': {
    const unsubscribe = auth.onAuthStateChanged(user => {
        unsubscribe();
        if (user) {
            db.collection('Users').doc(user.uid).get()
                .then(doc => {
                    if (doc.exists) {
                        sendResponse({ success: true, profile: doc.data() });
                    } else {
                        sendResponse({ success: false, error: "User profile not found." });
                    }
                })
        } else {
             sendResponse({ success: false, error: "User not authenticated." });
        }
    });
    return true;
}

The result was that the New User was indeed created in Firestore and Firebase Authentication, but it is failing two of the three tests. Here is the terminal output:



> [email protected] test
> NODE_OPTIONS=--experimental-vm-modules jest

(node:2283) ExperimentalWarning: VM Modules is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
 FAIL  tests/extension.test.js (12.447 s)
  Anotato Extension Tests
    Extension Loading
      ✓ should load the extension and find the service worker (2 ms)
    User Actions
      ✕ should show a signed-in state in the popup
      ✕ should allow a signed-in user to create an annotation

  ● Anotato Extension Tests › User Actions › should show a signed-in state in the popup

    Timed out waiting for user profile to be created by Cloud Function.

      83 |       }
      84 |       if (!userProfile) {
    > 85 |         throw new Error("Timed out waiting for user profile to be created by Cloud Function.");
         |               ^
      86 |       }
      87 |     });
      88 |

      at Object.<anonymous> (tests/extension.test.js:85:15)

  ● Anotato Extension Tests › User Actions › should allow a signed-in user to create an annotation

    Timed out waiting for user profile to be created by Cloud Function.

      83 |       }
      84 |       if (!userProfile) {
    > 85 |         throw new Error("Timed out waiting for user profile to be created by Cloud Function.");
         |               ^
      86 |       }
      87 |     });
      88 |

      at Object.<anonymous> (tests/extension.test.js:85:15)

Test Suites: 1 failed, 1 total
Tests:       2 failed, 1 passed, 3 total
Snapshots:   0 total
Time:        14.223 s
Ran all test suites.

Using PSD.js, how to output png as buffer?

In a Nodejs project, I am using PSD.js to generate a png from a psd. I am using the .toPng() method. I would like to go from this png object to a buffer without saving to the file system. I have tried Buffer.from(png) and I have tried using Sharp’s sharp(png).toBuffer() without luck. Sharp is then used to modify the png buffer.

const psd = new PSD(fileBuffer);
psd.parse();

if (!psd.image) {
    throw 'Error message';
}
const png = psd.image.toPng();
convBuffer = Buffer.from(png); 
             //await sharp(png).toBuffer() failed 
             //await png.get() failed

What is the global object inside a module in Node.js?

When I execute this code from the Node.js console, the function Foo can be found in the globalThis object ([Function: Foo]):

function Foo () { console.log ("Hello world!"); }
console.log (globalThis["Foo"]);

When I put this code in a module foo.mjs and run the code with the command line “node.js foo.mjs”, the Foo function cannot be found in globalThis.

From inside a module, what is the global object that contains the functions and variables defined in this module?

Join API endpoints and write out result

I would like to join endpoints and return result (in WordPress). After I get the results, I want to import with WP All Import plugin, Hotels and Locations. I’m using Traveler theme.

The API is: https://www.postman.com/filipnet-team/karpaten-webservice/collection/4gcaetc/karpaten-webservice

I made a diagramm too:
enter image description here

It should be joined the following way: Countries (->CountryDetails) -> Regions -> Resorts -> Hotels (->HotelDetails)

The results must be shown in a blank page.

What I tried – The other parts are working fine, except the 6th, where I tried to join the API Endpoints – Error: No countries returned from API / There has been a critical error on this website:

// ----------------------------
// 0. API_SECRET_TOKEN API 
// ----------------------------
// Generate a long random token once and paste it here
define('API_SECRET_TOKEN', 'a5ef2d6a717f47ddaf78d98a04e28e20');

add_action('init', function () {

    $api_pages = array(
        'kcountrylist-api' => array( /*CountryList*/
            'endpoint' => 'https://webservice.karpaten.ro/webservice/',
            'method'   => 'POST',
            'headers'  => array('Content-Type' => 'text/xml; charset=utf-8'),
            'body'     => '<root>
                           <head>
                           <auth>
                           <username>XML.naturatravel</username>
                           <password>naturatravel</password>
                           </auth>
                           <service>GetCountriesList</service>
                           </head>
                           <main></main>
                           </root>'
        ),
        'kcountrydet-api' => array( /*CountryDetails*/
            'endpoint' => 'https://webservice.karpaten.ro/webservice/',
            'method'   => 'POST',
            'headers'  => array('Content-Type' => 'text/xml; charset=utf-8'),
            'body'     => '<root>
                           <head>
                           <auth>
                           <username>XML.naturatravel</username>
                           <password>naturatravel</password>
                           </auth>
                           <service>GetCountryDetails</service>
                           </head>
                           <main>
                           <CountryID>{{CountryID}}</CountryID>
                           </main>
                           </root>'
        ),
        'kregionlist-api' => array( /*RegionList*/
            'endpoint' => 'https://webservice.karpaten.ro/webservice/',
            'method'   => 'POST',
            'headers'  => array('Content-Type' => 'text/xml; charset=utf-8'),
            'body'     => '<root>
                           <head>
                           <auth>
                           <username>XML.naturatravel</username>
                           <password>naturatravel</password>
                           </auth>
                           <service>GetRegionsList</service>
                           </head>
                           <main>
                           <CountryID>{{CountryID}}</CountryID>
                           </main>
                           </root>'
        ),
        'kregiondet-api' => array( /*RegionDetails*/
            'endpoint' => 'https://webservice.karpaten.ro/webservice/',
            'method'   => 'POST',
            'headers'  => array('Content-Type' => 'text/xml; charset=utf-8'),
            'body'     => '<?xml version="1.0" encoding="UTF-8"?>
                           <root>
                           <head>
                           <auth>
                           <username>XML.naturatravel</username>
                           <password>naturatravel</password>
                           </auth>
                           <service>GetRegionDetails</service>
                           </head>
                           <main>
                           <RegionID>{{RegionID}}</RegionID>
                           </main>
                           </root>'
        ),
        'kresortlist-api' => array( /*ResortList*/
            'endpoint' => 'https://webservice.karpaten.ro/webservice/',
            'method'   => 'POST',
            'headers'  => array('Content-Type' => 'text/xml; charset=utf-8'),
            'body'     => '<?xml version="1.0" encoding="UTF-8"?>
                           <root>
                           <head>
                           <auth>
                           <username>XML.naturatravel</username>
                           <password>naturatravel</password>
                           </auth>
                           <service>GetResortsList</service>
                           </head>
                           <main>
                           <CountryID>{{CountryID}}</CountryID>
                           <RegionID>{{RegionID}}</RegionID>
                           </main>
                           </root>'
        ),
        'kresortdet-api' => array( /*ResortDet*/
            'endpoint' => 'https://webservice.karpaten.ro/webservice/',
            'method'   => 'POST',
            'headers'  => array('Content-Type' => 'text/xml; charset=utf-8'),
            'body'     => '<?xml version="1.0" encoding="UTF-8"?>
                           <root>
                           <head>
                           <auth>
                           <username>XML.naturatravel</username>
                           <password>naturatravel</password>
                           </auth>
                           <service>GetResortDetails</service>
                           </head>
                           <main>
                           <ResortID>{{ResortID}}</ResortID>
                           </main>
                           </root>'
        ),
        'khotelslist-api' => array( /*Hotels*/
            'endpoint' => 'https://webservice.karpaten.ro/webservice/',
            'method'   => 'POST',
            'headers'  => array('Content-Type' => 'text/xml; charset=utf-8'),
            'body'     => '<?xml version="1.0" encoding="UTF-8"?>
                           <root>
                           <head>
                           <auth>
                           <username>XML.naturatravel</username>
                           <password>naturatravel</password>
                           </auth>
                           <service>GetHotelsList</service>
                           </head>
                           <main>
                                <!-- <ResortID>{{ResortID}}</ResortID> -->
                                <RegionID>{{RegionID}}</RegionID>
                                <CountryID>{{CountryID}}</CountryID>
                           </main>
                           </root>'
        ),
        'khoteldet-api' => array( /*Hotel Details*/
            'endpoint' => 'https://webservice.karpaten.ro/webservice/',
            'method'   => 'POST',
            'headers'  => array('Content-Type' => 'text/xml; charset=utf-8'),
            'body'     => '<?xml version="1.0" encoding="UTF-8"?>
                           <root>
                           <head>
                           <auth>
                           <username>XML.naturatravel</username>
                           <password>naturatravel</password>
                           </auth>
                           <service>GetHotelDetails</service>
                           </head>
                           <main>
                                <HotelID>{{HotelID}}</HotelID>
                           </main>
                           </root>'
        )
    );

    if (isset($_GET['api_page']) && isset($api_pages[$_GET['api_page']])) {

        if (!isset($_GET['token']) || $_GET['token'] !== API_SECRET_TOKEN) {
            status_header(403);
            wp_die('Forbidden: Invalid token');
        }

        $config = $api_pages[$_GET['api_page']];
        $method = strtoupper($config['method']);

        $body = $config['body'];

        // ---- Handle dynamic parameters ----
        if ($method === 'POST') {
            foreach ($_GET as $key => $value) {
                if (in_array($key, ['api_page','token','format'])) continue;
                $value = sanitize_text_field($value);
                $body = str_replace('{{'.$key.'}}', $value, $body);
            }

            if (stripos($config['headers']['Content-Type'], 'json') !== false) {
                $body_arr = json_decode($body, true);
                if (isset($body_arr['root']['main'])) {
                    foreach ($_GET as $key => $value) {
                        if (in_array($key, ['api_page','token','format'])) continue;
                        $body_arr['root']['main'][$key] = sanitize_text_field($value);
                    }
                }
                $body = json_encode($body_arr);
            }
            elseif (stripos($config['headers']['Content-Type'], 'xml') !== false) {
                $body = preg_replace('/&(?![a-zA-Z#0-9]+;)/', '&amp;', $body);
                $xml = new DOMDocument();
                $xml->loadXML($body);

                $main = $xml->getElementsByTagName('main')->item(0);
                foreach ($_GET as $key => $value) {
                    if (in_array($key, ['api_page','token','format'])) continue;
                    $found = $xml->getElementsByTagName($key)->item(0);
                    if (!$found) {
                        $el = $xml->createElement($key, htmlspecialchars($value, ENT_XML1 | ENT_COMPAT, 'UTF-8'));
                        $main->appendChild($el);
                    } else {
                        $found->nodeValue = htmlspecialchars($value, ENT_XML1 | ENT_COMPAT, 'UTF-8');
                    }
                }
                $body = $xml->saveXML();
            }
        }

        // ---- Build request ----
        $args = array(
            'method'  => $method,
            'headers' => $config['headers']
        );

        if ($method === 'POST') {
            $args['body'] = $body;
            $url = $config['endpoint'];
        } else {
            $params = $_GET;
            unset($params['api_page'], $params['token'], $params['format']);
            $url = add_query_arg($params, $config['endpoint']);
        }

        // ---- Send ----
        $response = wp_remote_request($url, $args);

        if (is_wp_error($response)) {
            wp_die($response->get_error_message());
        }

        $body = wp_remote_retrieve_body($response);

        // ---- Clean ----
        $body = html_entity_decode($body, ENT_QUOTES | ENT_HTML5 | ENT_SUBSTITUTE, 'UTF-8');
        $body = preg_replace('/>s+</', '><', $body);
        $body = preg_replace('/<!--.*?-->/s', '', $body);
        //$body = preg_replace('/<![CDATA[(.*?)]]>/', '$1', $body);
        $body = preg_replace('/&(?![a-zA-Z#0-9]+;)/', '&amp;', $body);

        // ---- Output ----
        $format = isset($_GET['format']) ? strtolower($_GET['format']) : 'json';

        if ($format === 'xml') {
            if (stripos($body, '<?xml') === 0) {
                header('Content-Type: application/xml; charset=utf-8');
            } else {
                header('Content-Type: application/json; charset=utf-8');
            }
            echo $body;
            exit;
        }

        // Else: convert to JSON
        $data = null;
        if (stripos($body, '<?xml') === 0 || stripos($body, '<root') !== false) {
            libxml_use_internal_errors(true);
            $xml = simplexml_load_string($body, 'SimpleXMLElement', LIBXML_NOCDATA);
            if ($xml !== false) {
                $data = simplexml_to_array_keep_html($xml,false);
            }
        }

        if ($data === null) {
            $json = json_decode($body, true);
            if (json_last_error() === JSON_ERROR_NONE) {
                $data = $json;
            } else {
                $data = ['raw' => $body];
            }
        }

        header('Content-Type: application/json; charset=utf-8');
        echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        exit;
    }
});
function simplexml_to_array_keep_html($xml, $encode_html = true)
{
    $arr = [];

    foreach ($xml->children() as $key => $child) {
        if ($child->count() > 0) {
            $value = simplexml_to_array_keep_html($child, $encode_html);
        } else {
            $raw = trim($child->asXML());
            $inner = preg_replace('/^<[^>]+>|</[^>]+>$/', '', $raw);

            // Encode HTML if requested
            if ($encode_html) {
                $inner = htmlentities($inner, ENT_QUOTES | ENT_HTML5, 'UTF-8');
            }

            $value = $inner;
        }

        if (isset($arr[$key])) {
            if (!is_array($arr[$key]) || !isset($arr[$key][0])) {
                $arr[$key] = [$arr[$key]];
            }
            $arr[$key][] = $value;
        } else {
            $arr[$key] = $value;
        }
    }

    return $arr;
}
// ----------------------------
// 5. Examples
// ----------------------------
/*1. https://test.naturatravel.ro/?api_page=kcountrylist-api&token=a5ef2d6a717f47ddaf78d98a04e28e20*/
/*2. https://test.naturatravel.ro/?api_page=kcountrydet-api&token=a5ef2d6a717f47ddaf78d98a04e28e20&CountryID=187*/
/*3. https://test.naturatravel.ro/?api_page=kregionlist-api&token=a5ef2d6a717f47ddaf78d98a04e28e20&CountryID=215*/
/*4. https://test.naturatravel.ro/?api_page=kregiondet-api&token=a5ef2d6a717f47ddaf78d98a04e28e20&RegionID=325*/
/*5. https://test.naturatravel.ro/?api_page=kresortlist-api&token=a5ef2d6a717f47ddaf78d98a04e28e20&CountryID=215&RegionID=325*/
/*6. https://test.naturatravel.ro/?api_page=kresortdet-api&token=a5ef2d6a717f47ddaf78d98a04e28e20&ResortID=2133*/
/*7. https://test.naturatravel.ro/?api_page=khotelslist-api&token=a5ef2d6a717f47ddaf78d98a04e28e20&RegionID=75&CountryID=7 */
/*8. https://test.naturatravel.ro/?api_page=khoteldet-api&token=a5ef2d6a717f47ddaf78d98a04e28e20&HotelID=29274 */
// ----------------------------
// Preserve HTML in post_content
// ----------------------------
add_filter('wpgetapi_api_to_posts_before_insert_post', function($post_data, $item, $map) {

    // Apply only to st_location posts
    if ($post_data['post_type'] === 'st_location') {

        foreach($map as $field_map) {
            if($field_map['post_field'] === 'post_content') {
                $api_field = $field_map['api_field'];
                if(isset($item[$api_field])) {
                    // Insert raw HTML from API
                    $post_data['post_content'] = $item[$api_field];
                }
            }
        }
    }

    return $post_data;

}, 10, 3);
// ----------------------------
// 6. Custom Combined Hotels API
// ----------------------------
// ----------------------------
// 0. API_SECRET_TOKEN
// ----------------------------
//define('API_SECRET_TOKEN', 'a5ef2d6a717f47ddaf78d98a04e28e20');

// ----------------------------
// Helper: fetch JSON from URL
// ----------------------------
function fetch_json($url) {
    $res = wp_remote_get($url);
    if (is_wp_error($res)) return null;
    $body = wp_remote_retrieve_body($res);
    $data = json_decode($body, true);
    return $data ?: null;
}

// ----------------------------
// Full Hotels JSON
// ----------------------------
add_action('init', function() {

    if(isset($_GET['api_page']) && $_GET['api_page'] === 'kfull-hotels-json') {

        if(!isset($_GET['token']) || $_GET['token'] !== API_SECRET_TOKEN){
            status_header(403);
            wp_die('Forbidden: Invalid token');
        }

        $endpoint = 'https://test.naturatravel.ro/';
        $token = $_GET['token'];
        $final = [];

        // 1️⃣ Countries
        $countries_data = fetch_json("$endpoint?api_page=kcountrylist-api&token=$token");
        if(!$countries_data || !isset($countries_data['GetCountriesList']['CountriesList']['Country'])) {
            wp_die('No countries returned from API');
        }

        $countries = (array)$countries_data['GetCountriesList']['CountriesList']['Country'];

        foreach($countries as $country) {
            $c_id = $country['ID'];
            $c_name = $country['Name'];
            $c_code = $country['CodIso2'] ?? '';

            // 2️⃣ CountryDetails
            $c_det_data = fetch_json("$endpoint?api_page=kcountrydet-api&token=$token&CountryID=$c_id");
            $c_desc = $c_det_data['GetCountryDetails']['Country']['Description'] ?? '';

            // 3️⃣ Regions list
            $regions_data = fetch_json("$endpoint?api_page=kregionlist-api&token=$token&CountryID=$c_id");
            $regions_arr = [];
            if(isset($regions_data['GetRegionsList']['RegionsList']['Region'])) {
                $regions = (array)$regions_data['GetRegionsList']['RegionsList']['Region'];
                foreach($regions as $region) {
                    $r_id = $region['ID'];
                    $r_name = $region['Name'];

                    // 4️⃣ Resort list
                    $resorts_data = fetch_json("$endpoint?api_page=kresortlist-api&token=$token&CountryID=$c_id&RegionID=$r_id");
                    $resorts_arr = [];
                    if(isset($resorts_data['GetResortsList']['ResortsList']['Resort'])) {
                        $resorts = (array)$resorts_data['GetResortsList']['ResortsList']['Resort'];
                        foreach($resorts as $resort) {
                            $res_id = $resort['ID'];
                            $res_name = $resort['Name'];

                            // 5️⃣ Hotels list
                            $hotels_data = fetch_json("$endpoint?api_page=khotelslist-api&token=$token&CountryID=$c_id&RegionID=$r_id");
                            $hotels_arr = [];
                            if(isset($hotels_data['GetHotelsList']['HotelsList']['Hotel'])) {
                                $hotels = (array)$hotels_data['GetHotelsList']['HotelsList']['Hotel'];
                                foreach($hotels as $hotel) {
                                    $h_id = $hotel['ID'];
                                    $h_name = $hotel['Name'];
                                    $h_stars = $hotel['Stars'] ?? '';

                                    // 6️⃣ HotelDetails
                                    $h_det_data = fetch_json("$endpoint?api_page=khoteldet-api&token=$token&HotelID=$h_id");
                                    $h_desc = $h_det_data['GetHotelDetails']['Hotel']['Description'] ?? '';
                                    $h_policies = $h_det_data['GetHotelDetails']['Hotel']['Policies'] ?? '';

                                    $hotels_arr[] = [
                                        'hotel_id' => $h_id,
                                        'hotel_name' => $h_name,
                                        'stars' => $h_stars,
                                        'description' => $h_desc,
                                        'policies' => $h_policies
                                    ];
                                }
                            }

                            $resorts_arr[] = [
                                'resort_id' => $res_id,
                                'resort_name' => $res_name,
                                'hotels' => $hotels_arr
                            ];
                        }
                    }

                    $regions_arr[] = [
                        'region_id' => $r_id,
                        'region_name' => $r_name,
                        'resorts' => $resorts_arr
                    ];
                }
            }

            $final[] = [
                'country_id' => $c_id,
                'country_name' => $c_name,
                'country_code' => $c_code,
                'description' => $c_desc,
                'regions' => $regions_arr
            ];
        }

        header('Content-Type: application/json; charset=utf-8');
        echo json_encode($final, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        exit;
    }

});

Azure App Service (PHP 7.x) showing “No Request” after cloning, both original and cloned apps not responding [closed]

I have a PHP 7.x web app hosted on Azure App Service.
It was running perfectly fine until I used the “Clone App” option in the Azure Portal to duplicate it within the same resource group and region.

After cloning, both the original and the cloned apps stopped responding, when I click Browse, the browser just shows: No Request

Here’s what I’ve checked so far:

Both App Services are in Running state

Files (including index.php) exist under /site/wwwroot/ in Kudu

Kudu console works fine

Stack in Configuration → General settings is still set to PHP 7.x

Created a simple phpinfo.php file → same “No Request” output

Restarted both apps multiple times

It looks like IIS or the FastCGI PHP handler isn’t processing requests anymore after cloning, but there are no errors in the log stream.

Is there a way to restore PHP handling or reconfigure FastCGI after cloning?
Or does the clone process break PHP runtime mapping in some way?

how to make a html contact form send message using html [duplicate]

I’m currently doing a project that involves making a contact form for a website. I would like to know how can I make the form send the message to the recipient using html and php. the php code also appears every time I click the send button.

This is what I’ve tried so far.

<form action="POST" action="st.php">
  <p>
    <label for="first">First Name:</label>
    <input type="text" id="firstname" name="user_first">
  </p>
  <p>
    <label for="last">Last name:</label>
    <input type="text" id="lastname" name="user_last">
  </p>
  <p>
    <label for="email">Email:</label>
    <input type="text" id="email" name="user_email">
  </p>
  <p>
    <label for="message">Message:</label>
    <textarea  type="text" id="message" name="user_message"></textarea>
  </p>
  <p class="button">
    <button type="submit" id="submit" name="submit">Send</button>
  </p>
</form>
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // Get POST data
    $firstname = isset($_POST['firstname']) ? strip_tags(trim($_POST['firstname'])) : '';
    $lastname = isset($_POST['lastname']) ? strip_tags(trim($_POST['lastname'])) : '';
    $email = isset($_POST['Email']) ? trim($_POST['Email']) : '';
    $message = isset($_POST['message']) ? strip_tags(trim($_POST['message'])) : '';
    $button = isset($_POST['button']) ? strip_tags(trim($_POST['button'])) : '';

    // Validate form fields
    if (empty($first)) {
        $errors[] = 'First Name is empty';
    }
    
    if (empty($last)) {
        $errors[] = 'Last Name is empty';
    }


    if (empty($email)) {
        $errors[] = 'Email is empty';
    } else if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors[] = 'Email is invalid';
    }

    if (empty($message)) {
        $errors[] = 'Message is empty';
    }
    

    // If no errors, send email
    if (empty($errors)) {
        // Recipient email address (replace with your own)
        $recipient = "[email protected]";
?>

How to Connect Sanmar API in WordPress WooCommerce REST API? [closed]

I’m trying to integrate the Sanmar Web Services API with my WooCommerce store in WordPress. I want to import products and keep inventory updated using the API.

I have received the following from Sanmar:

WSDL URL for API

SFTP access to download CSV files (SanMar_SDL_N.csv, SanMar_EPDD.csv, sanmar_dip.txt)

Credentials (Username & Password) via a secure Bitwarden link

My questions:

How can I connect the Sanmar API directly with WooCommerce?

Which WordPress/WooCommerce plugins are recommended for SOAP API integration?

How to handle bulk product import (getProductBulkInfo) and inventory updates efficiently?

Do I need to create a custom plugin or is there a ready solution?

I’m new to WooCommerce REST API and SOAP integration, so any guidance, code snippets, or plugin recommendations will be really helpful.

Thanks in advance!

note: I purchased the WooCommerce API Product Sync with WooCommerce REST APIs plugin to connect Sanmar API and sync products and inventory automatically , or any easy way to connect.

Getting WooCommerce “View Product” Link To Appear Everywhere

I have this code that I have added to WP site using the Snippets plugin. The code is intended to display a “View Product” link in addition to the “Add to Cart” button for WooCommerce.

The code works! It shows the “View Product” link as needed.

THE ISSUE:

The issue however is that the “View Product” link only appears on the Shop page (which displays all items on the store) and on the item Categories/Tags pages.

The “View Product” link doesn’t appear for Related Products, Cross Sells, or Handpicked Products, etc.

I need the “View Product” link to appear for all items wherever they are displayed on the website.

I could really use some help with this. Thanks in advance!

This is the code that I have implemented:

    /**
* @snippet Add ‘View Product’ button before ‘Add to Cart’ in WooCommerce
* @compatible WC 6.3.1
*/
add_action('woocommerce_after_shop_loop_item', 'wptechnic_custom_button_view_product', 5 );
function wptechnic_custom_button_view_product() {
    global $product;

    /* Ignore for Variable and Group products
    if( $product->is_type('variable') || $product->is_type('grouped') ) return;
    */

    // Display the custom button
    echo '<a style="margin-right:5px" class="button wptechnic-custom-button-view-product" href="' . esc_attr( $product->get_permalink() ) . '">' . __('View product') . '</a>';
}

Radix UI Dialog Overlay disappears when switching browser tabs (Next.js + ShadCN)

I’m using Radix UI Dialog (via ShadCN UI) in my Next.js 13+ project.
Everything works fine when I open the dialog — the overlay (bg-black/80) appears as expected and blocks the background.

However, if I switch browser tabs (or minimize the Chrome window) and then return to the tab again,
the black overlay disappears, but the dialog content stays visible and interactive.
So it looks like the dialog is floating on the screen without any dimmed background.

This only happens after tab focus changes — not when opening or closing normally.

and i use it like this

<Dialog open={open} onOpenChange={setOpen}>
  <DialogTrigger asChild>
    <button onClick={() => setOpen(true)}>Open Dialog</button>
  </DialogTrigger>
  <DialogContent>
    <p>Dialog content here</p>
  </DialogContent>
</Dialog>

and my dialog.tsx is like this

"use client"

import * as React from "react"
import * as DialogPrimitive from "@radix-ui/react-dialog"
import { X } from "lucide-react"
import { cn } from "@/lib/utils"

const Dialog = ({ children, ...props }: React.ComponentPropsWithoutRef<typeof DialogPrimitive.Root>) => (
  <DialogPrimitive.Root {...props}>{children}</DialogPrimitive.Root>
)

const DialogTrigger = DialogPrimitive.Trigger
const DialogPortal = DialogPrimitive.Portal
const DialogOverlay = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Overlay>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
  <DialogPrimitive.Overlay
    ref={ref}
    className={cn(
      "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out",
      className
    )}
    {...props}
  />
))
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName

const DialogContent = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Content>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => (
  <DialogPortal>
    <DialogOverlay />
    <DialogPrimitive.Content
      ref={ref}
      className={cn(
        "fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 border bg-background p-6 sm:rounded-lg shadow-lg",
        className
      )}
      {...props}
    >
      {children}
      <DialogPrimitive.Close className="absolute right-4 top-4">
        <X className="h-4 w-4" />
      </DialogPrimitive.Close>
    </DialogPrimitive.Content>
  </DialogPortal>
))
DialogContent.displayName = DialogPrimitive.Content.displayName

export { Dialog, DialogTrigger, DialogContent }

and when i try to close the dialog whose overlay is already removed then it show me this error

Error: Failed to execute ‘removeChild’ on ‘Node’: The node to be
removed is not a child of this node.

Hamburger menu opens but links are not clickable and background darkens [closed]

I’m building a responsive navigation menu for my website. The hamburger menu opens correctly and darkens the background, but I can’t click on any of the links inside the menu. Clicking anywhere outside closes it. It’s live at http://testingpf.great-site.net/

enter image description here

I tried changing CSS and JavaScript. I worked a lot but still couldn’t find error and fix it.

Expected: I should be able to click the links when the menu is open.

Actual: Menu opens but links are not clickable; only closes when I click outside.

What am I missing? Is this a z-index or layering issue?

const toggle = document.getElementById('navToggle');
const nav = document.querySelector('.main-nav');
const overlay = document.createElement('div');
overlay.className = 'nav-overlay';
document.body.appendChild(overlay);

toggle.addEventListener('click', () => {
  nav.classList.toggle('nav-open');
  overlay.classList.toggle('active');
});
overlay.addEventListener('click', () => {
  nav.classList.remove('nav-open');
  overlay.classList.remove('active');
});
.main-nav {
  position: fixed;
  top: 0; right: -100%;
  width: 320px; height: 100vh;
  background: #fff;
  transition: right 0.3s ease;
  z-index: 1000;
}

.main-nav.nav-open { right: 0; }

.nav-overlay {
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 100%;
  background: rgba(11,42,74,0.5);
  z-index: 999;
  display: none;
}

.nav-overlay.active { display: block; }
<header class="site-header">
  <div class="container header-inner">
    <a class="brand" href="/">
      <img src="assets/img/profile.jpg" alt="Zohaib Ashraf Noori" class="brand-photo">
      <div class="brand-text">
        <h1>Zohaib Ashraf Noori</h1>
        <p class="muted">Accounting • Islamiat • Pakistan Studies</p>
      </div>
    </a>

    <nav class="main-nav">
      <a href="/" class="active">Home</a>
      <a href="/about">About</a>
      <a href="/notes">Notes</a>
      <a href="/classes" class="cta">Classes</a>
    </nav>

    <button class="nav-toggle" id="navToggle">☰</button>
  </div>
</header>