Cannot connect to mqtt broker via browser JS

I’ve a project where I’m using mqtt (HiveMQ for prototyping) for bi-directional communication. I can access the receiver via Hive’s web client but how do I implement it in browser JS?

I’ve downloaded a local copy of mqtt.min.js from here and placed it in my JS folder:

WEBFOLDER

+-- index.htm
|
+-- JS
     |
     +-- main.js
     |
     +-- mqtt.min.js

HTML:

<!DOCTYPE html>
<!-- Document started 22/11/2023  by BTV -->
<html>
    
    <head>
        <meta charset="UTF-8">
        <title>COMMANDER</title>        
        <!--    JS-->
        <script type="text/javascript" src="./JS/mqtt.min.js"></script>
        <script type="text/javascript" src="./JS/main.js"></script>
    </head>
    
    
    <body>
        Loaded...
    </body>
</html>

main.js:

const options = {
                "clientId": "random",
                "keepalive": 60,
                "connectTimeout": 3000,
                "clean": true,
                "protocolId": "MQIsdp",
                "protocolVersion": 3
            }

const client = mqtt.connect('https://55ab****83811.s1.eu.hivemq.cloud', options);

client.on("connect", () => {
  client.subscribe("tcontrol", (err) => {
    console.log("Connected...");
    if (!err) {
      client.publish("tcontrol", "Hello mqtt");
    }
  });
});

client.on("message", (topic, message) => {
  // message is Buffer
  console.log(message.toString());
  client.end();
});

client.on('offline', () => {
  console.log('Client is offline');
});

client.on('reconnect', () => {
  console.log('Reconnecting to MQTT broker');
});

client.on('end', () => { 
  console.log('Connection to MQTT broker ended');
});

All I get from Firefox is the errors:

Firefox can’t establish a connection to the server at wss://55a***********db376d783811.s1.eu.hivemq.cloud/. mqtt.min.js:5:10448

and

The connection to wss://55ab4d************6d783811.s1.eu.hivemq.cloud/ was interrupted while the page was loading.

And from Safari:

failed: WebSocket is closed before the connection is established.

I’ve tried changing the url protocol to ws, wss, http, https and mqtt.

I’ve also tried importing directly from the UNPKG link so not using a local download but with the same issues.

Odoo 16 Portal widget not working for public users

In Odoo v16 Template form, I have a selection field “Activity Type” that contains records from backend (like Many2many-tags widget but now in Portal), will be chosen by the user, and the user can choose more than 1 record.

Depending on the chosen records, new 3 fields for each Activity type (divs) will appear and become mandatory.

This code is functioning flawlessly when logged in as a portal user. However, when a public user accesses this form, the field titled “Activity Type” appears, allowing me to select multiple records. However, the sections (divs) that are required to appear do not appear.

<div class="col-md-12"
 style="padding-top: 20px !important; padding-bottom: 20px !important;">
<label class="form-label" for="activity_type_ids">Activity Type</label>
<span
        style="color: red;"> *
</span>
<select class="form-control js-example-basic-multiple col-xl-6 mb-1 new-get_data"
        multiple="multiple" name="activity_type_ids" required="1"
        id="activity_type_ids">
    <t t-foreach="activity_ids" t-as="activity">
        <option t-att-value="activity" t-esc="activity.name"/>
    </t>
</select>
<input type="hidden" id="hidden_activity_ids" name="hidden_activity_ids"/>
<input type="hidden" id="hidden_activity_codes"
       name="hidden_activity_codes"/>
<!-- Div for Construction Fields -->

<div class="col-md-6 activity-section" id="construction_fields"
 style="padding-top: 20px !important; padding-bottom: 20px !important;">
<label class="form-label">Construction CR Number</label>
<input type="text" class="form-control" name="construction_cr_number"
       placeholder="Construction CR Number"/>

<label class="form-label">Construction CR</label>
<span style="color: red;">
    *
</span>
<input type="file" class="form-control" name="construction_cr"
       accept="application/pdf"/>

<label class="form-label">Construction Activity Register</label>
<input type="file" class="form-control"
       name="construction_activity_register" accept="application/pdf"/>
  <!-- Div for Maintenance and Operation Fields -->
  <div class="col-md-6 activity-section" id="maintenance_fields"
     style="padding-top: 20px !important; padding-bottom: 20px !important;">
    <label class="form-label">Maintenance CR Number</label>
    <span
            style="color: red;"> *
    </span>
    <input type="text" class="form-control" name="maintenance_cr_number"
           placeholder="Maintenance CR Number"/>

    <label class="form-label">Maintenance CR</label>
    <span style="color: red;">
        *
    </span>
    <input type="file" class="form-control" name="maintenance_cr"
           accept="application/pdf"/>

    <label class="form-label">Maintenance Activity Register</label>
    <span
            style="color: red;"> *
    </span>
    <input type="file" class="form-control" name="maintenance_activity_register"
           accept="application/pdf"/>
</div>

<!-- ETC... -->

The related JS (which is not working for public users) is:

odoo.define('custom_field.Many2many_tag', function (require) {
var PublicWidget = require('web.public.widget');
var rpc = require('web.rpc');
const { _lt } = require('web.core');

// Used in new_supplier_registration_request template
var NewData = PublicWidget.Widget.extend({
    selector: '.new-get_data',
    start: function () {
        this._super.apply(this, arguments);

        // Initialize the select2 widget
        $('.js-example-basic-multiple').select2({
            placeholder: _lt('Select Activities'),
            allowClear: true,
        });

        // Hide all activity sections initially on page load
        $('.activity-section').hide();

        // Add an event listener to capture selected values
        $('#activity_type_ids').on('change', function () {
            // Get the selected values
            var selectedValues = $(this).val();

            // Parse the IDs from the selected values as integers
            var selectedIds = selectedValues.map(function (value) {
                return parseInt(value.match(/d+/)[0], 10);
            });

            // Perform an RPC call to get the activity codes based on selected IDs
            rpc.query({
                model: 'supplier.registration.activity',
                method: 'read',
                args: [selectedIds, ['code']],
            }).then(function (records) {
                var codes = records.map(function (record) {
                    return record.code;
                });

                // Clear all activity sections initially
                $('.activity-section').hide();
                $('input').removeAttr('required'); // Remove required attribute from all inputs

                // Iterate over codes to show the relevant divs and set required attributes
                codes.forEach(function (code) {
                    switch (code) {
                        case 'construction':
                            $('#construction_fields').show(); // Show construction fields
                            $('#construction_fields input').attr('required', true); // Set required attribute for all inputs in the div
                            break;
                        case 'maintenance':
                            $('#maintenance_fields').show();
                            $('#maintenance_fields input').attr('required', true);
                            break;
                        case 'education':
                            $('#education_fields').show();
                            $('#education_fields input').attr('required', true);
                            break;
                        case 'food_supplies':
                            $('#food_supplies_fields').show();
                            $('#food_supplies_fields input').attr('required', true);
                            break;
                        case 'equipment_supplies':
                            $('#equipment_supplies_fields').show();
                            $('#equipment_supplies_fields input').attr('required', true);
                            break;
                        case 'medical_equipment':
                            $('#medical_equipment_fields').show();
                            $('#medical_equipment_fields input').attr('required', true);
                            break;
                        case 'event_organization':
                            $('#event_organization_fields').show();
                            $('#event_organization_fields input').attr('required', true);
                            break;
                        default:
                            console.log("No matching activity found for code:", code);
                    }
                });

                // Set the hidden input field with the retrieved activity codes
                $('#hidden_activity_codes').val(codes.join(','));

                // Also set the hidden input with the selected IDs
                $('#hidden_activity_ids').val(selectedIds.join(','));
            });
        });
    },
});

PublicWidget.registry.Many2many_tag = NewData;
return NewData;
});

Tom Select: How to display all returned results but clear the state at every request?

My server callback already pre-filters the data and I want Tom Select to display all the results returned for the given query. I’ve tried to achieve this by setting searchField: []. However, this also keeps results of previously typed queries.

Examples:

  1. bad: missing results:
  • User searches for “Zurich” or “St Gallen”
  • The server returns “Zürich” or “St. Gallen”, but Tom Select discards those results because they do not match the typed string.
  • Conclusion: I want Tom Select to display all returned results.
  1. bad: old results:
  • User searches for “Zurich”, then “St Gallen” (typing slowly and erasing the previous search with backspace)
  • Results contain Zur, Zuric, Zurich, St, St Ga, St Gallen
  • Conclusion: I want Tom Select to only display the results of the most recent query to the server
  1. good: what I’d need instead:
  • User searches for “Zurich”, then “St Gallen” (typing slowly and erasing the previous search with backspace)
  • As soon as the user has finished typing “Zurich”, the result “Zürich” is displayed.
  • As the user erases “Zurich” and finishes typing “St Gallen”, the result “St. Gallen” is displayed.

Which combination of options allows me to cause this behavior?

Is it safe to echo back the Origin header in CORS responses without re-checking the whitelist in AWS Lambda?

We’re developing an API using AWS Lambda functions. We have a single Lambda that handles all OPTIONS requests for CORS preflight checks. This Lambda verifies the Origin against a whitelist and, if valid, responds with:

{
  'Access-Control-Allow-Origin': 'https://exampledomain.com',
  'Access-Control-Allow-Credentials': 'true'
}

For the actual API request (e.g., a POST or GET), we also want to include the same headers in the response to allow the browser to process the request correctly. However, we’re wondering if it’s safe to simply echo back the Origin value from the incoming request in the actual response instead of performing another whitelist validation.

For example:

OPTIONS request:

The Origin is checked against a whitelist.
If valid, the Lambda responds with a 200 status and the CORS headers.

Actual request (e.g., POST):

Instead of re-checking the Origin, we echo the Origin value in the Access-Control-Allow-Origin header, like so:

{
  'Access-Control-Allow-Origin': request.headers.origin,
  'Access-Control-Allow-Credentials': 'true'
}

My questions are:

Is this approach secure, assuming the whitelist validation happens during the OPTIONS request?
Are there any potential pitfalls or best practices we should consider here?

Thanks for any advice!

Issue with Loading CSS and JS Files in WebView from MAUI Resources Folder

I am building a .NET MAUI app and am trying to render an HTML file in a WebView. The HTML file needs to load external CSS and JavaScript files that are located in the Resources/FirecodeRequirements folder of my MAUI project.

I’ve followed the steps to include the assets, but they are not loading correctly in the WebView. Here are the details of my setup:

Folder Structure:

/Resources
    └── /FirecodeRequirements
        ├── index.html
        ├── styles.css
        └── script.js

Build Action:

  • I’ve set the Build Action for all the files (index.html, styles.css, script.js) to MauiAsset.

HTML File (index.html):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Fire Code Requirements</title>
    <!-- Correct Path to CSS -->
    <link rel="stylesheet" href="FirecodeRequirements/styles.css">
</head>
<body>
    <div class="table_component page active">
        <table>
            <tr><th>Page 1</th></tr>
            <tr><td>Content for page 1</td></tr>
        </table>
        <div class="navigation-btns">
            <button class="prevBtn" disabled>Previous</button>
            <button class="nextBtn">Next</button>
        </div>
    </div>

    <!-- Correct Path to JS -->
    <script src="FirecodeRequirements/script.js"></script>
</body>
</html>

MAUI Code to Load the HTML:

var webView = new WebView
{
    Source = "Resources/FirecodeRequirements/index.html"
};

Problem:

  • The HTML is loading correctly, but CSS and JavaScript are not applied (styles and scripts are not working).
    -I’ve tried different variations of the file paths but the CSS and JS files still aren’t loading.

What I’ve Tried:

  • Ensured the Build Action for the CSS, JS, and HTML files is set to MauiAsset.
  • Made sure the paths in the HTML file are correct and reflect the folder structure (FirecodeRequirements/).
  • Cleaned and rebuilt the project.
  • Verified the app is running correctly on the device, but the styles and scripts are not applied.

Question:
How can I correctly load CSS and JavaScript files from the Resources folder into a WebView in .NET MAUI? Is there a specific way to reference the asset files that I might be missing?

Any guidance on what could be going wrong would be much appreciated!

How to display preview of HTML content same as browser’s print preview?

I need to create a preview feature that shows users exactly how their HTML content will look when printed by the browser, without actually printing or showing any print dialogs.

Problem:
I have an HTML editor where users create content with specific print styles (A4 format, margins, page breaks, etc.). Before printing, I want to show user exactly how their content will appear when printed by the browser. The preview must be exact same with the actual browser print output, as this is crucial for my use case.

Why Integrating Other Libraries Don’t Work:
Libraries like jsPDF, html2Pdf or other PDF generation libraries don’t produce the exact same output as the browser’s print engine. The differences in rendering, content positions and page breaks styles make these solutions inadequate for my needs.

Is there a way to:

  1. Access browser’s print preview rendering engine programmatically?
  2. Display the preview without triggering the print dialog?

how do i manipulate my javascript based automation framework to mouse over i.e the pointer to hover over a menu item?

I am currently experimenting with the automation UI test framework called Nightwatch.js.
I am trying to get my test to manipulate the mouse to hover over a menu item with submenus.
It keeps failing.

I want to get it to look like this in the below screenshot:
what i want my automation script to do so that it can click on one of the submenus

Please can anybody provide recommendations or help?

The below code is my test scripts.

describe('Test for all things on the portal ui', function(){
    it('Test navigation to the claims portal ui', function(browser){
        let shared = browser.page.commonStuff();

        shared
            .navigate()
            .login()

        let portals = browser.page.portalsPage();
        portals.expect.section('@menu').to.be.visible;

        let menuSection = portals.section.menu;

        menuSection.perform(function() {
            const actions = this.actions({async: true});


            return actions
            .mouse()
            .move(300,{origin : element('@menu')},94,45)
            .mouse()
            .pause(10000);
            
        })

       
        menuSection.expect.element('@admin').to.be.visible;
        menuSection.expect.element('@claims').to.be.visible;

        menuSection.click('@claims');
        
        
        browser.end();
          

    });
});

The execution log produces this message:

PS C:nmautobitbucketProject> npx nightwatch test/portalsTest.js


[Test for all things on the portal ui] Test Suite
───────────────────────────────────────────────────────────────────────────────
ℹ Connected to GeckoDriver on port 4444 (5142ms).
  Using: firefox (132.0.1) on WINDOWS.


  Running Test navigation to the claims portal ui:
───────────────────────────────────────────────────────────────────────────────────────────────────────
  ℹ Loaded url https://test.natmed.mobi in 1280ms
  √ Element <body> was visible after 114 milliseconds.
  √ Expected element @menu <#PortalsIndex> to be visible (1169ms)
12 Nov 08:42:19  ✖ TypeError
   Error while running "perform" command: [TypeError] actions.mouse(...).move(...).mouse is not a function
      - writing an ES6 async test case? - keep in mind that commands return a Promise; 
      - writing unit tests? - make sure to specify "unit_tests_mode=true" in your config.

    Error location:
    C:nmautobitbucketProjecttestportalsTest.js:21
    ––––––––––––––––––––––––––––––––––––––––––––––––
     19 |             .mouse()
     20 |             .move(300,{origin : element('@menu')},94,45)
     21 |             .mouse() 
     22 |             .pause(10000);
     23 |
    ––––––––––––––––––––––––––––––––––––––––––––––––

    Stack Trace :
    at NightwatchAPI.<anonymous> (C:nmautobitbucketProjecttestportalsTest.js:21:14)
    at Object.apply (C:nmautobitbucketProjectnode_modulesnightwatchlibapi_loaders_base-loader.js:411:29)
    at CommandInstance.runCallback (C:nmautobitbucketProjectnode_modulesnightwatchlibapiclient-commandsperform.js:122:17)
    at CommandInstance.command (C:nmautobitbucketProjectnode_modulesnightwatchlibapiclient-commandsperform.js:74:27)
    at C:nmautobitbucketProjectnode_modulesnightwatchlibapi_loaderscommand.js:182:29
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)


  FAILED: 1 assertions failed and  2 passed (14.877s)

───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  ️TEST FAILURE (22.681s):
   - 1 assertions failed; 2 passed

   × 1) portalsTest

   – Test navigation to the claims portal ui (14.877s)

   → TypeError
   Error while running "perform" command: [TypeError] actions.mouse(...).move(...).mouse is not a function

    Error location:
    C:nmautobitbucketProjecttestportalsTest.js:21
    ––––––––––––––––––––––––––––––––––––––––––––––––
     19 |             .mouse()
     20 |             .move(300,{origin : element('@menu')},94,45)
     21 |             .mouse() 
     22 |             .pause(10000);
     23 |
    ––––––––––––––––––––––––––––––––––––––––––––––––

Why can’t I assign percentage values to CSS using React Javascipt?

I have the following code which plots a bargraph component on the screen:

import '../styles/GraphBar.css'

function GraphBar({value, maxLength}) {

     const height = (value / maxLength) * 100 + "%"  
     const style = {height: height}

  return (

    <div className="graph-bar">

        <p className="graph-value">{value}</p>
        <div className="graph-picture" style={style}></div>

    </div>
)}

export default GraphBar

I know the program works if I give the values in pixels, problem is I need to use percentages for the height to have it be responsive no matter the size of the screen it’s viewed on. The above calculation gives the correct result, problem is it seems to refuse to interpret the percentage value and the code compiles as if no value was assigned as height, showing no bars. In fact, even if I write a random constant like “70%” as the height value directly into the style prop, it still refuses to interpret it, even though everywhere I looked they say that’s exactly how it should work. What is the issue here?

How to Append MP4 Chunks to a Single Blob in Azure Blob Storage Without Playback Issues?

I’m building a service using the MediaRecorder API to record a user’s webcam media stream. For compatibility, I’m using the MIME type video/mp4; codecs=avc1.64001F,mp4a.40.2 which supports recording and playback in both Chrome and Safari.

To prevent loss of recorded footage in case of unexpected interruptions (e.g., browser crash, power shutdown), I plan to upload each recorded chunk to Azure Blob Storage every second.

However, I want to manage the recording as a single video blob instead of creating multiple blobs for each start/stop of the recording session, simulating the feel of a single, uninterrupted video file. To achieve this, I’m considering using an append blob in Azure.

The issue is that this approach may result in playback issues due to metadata or timestamp conflicts within the merged chunks on Azure.

How can I resolve this problem?

(Note: I’d prefer not to use solutions involving ffmpeg, mp4box, or other WASM libraries due to dependency on user computer performance. Additionally, implementing a separate server for MP4 file merging is also a last-resort solution due to the added complexity.)

“You may need an additional loader to handle the result of these loaders” – issues with babel config potentially

Currently working with @mui/x-charts and keep getting the same error no matter what I try. I was trying to work with Chart.js and was getting errors to.

./node_modules/@mui/base/Popper/Popper.js 151:27
Module parse failed: Unexpected token (151:27)
File was processed with these loaders:
 * ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
|   }
|   const classes = useUtilityClasses();
>   const Root = slots.root ?? 'div';
|   const rootProps = useSlotProps({
|     elementType: Root,

NPM version 10.2.4

React 18.3.1

and here is my package.json

{
  "name": "website",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@emotion/react": "^11.13.3",
    "@emotion/styled": "^11.13.0",
    "@mui/x-charts": "^6.18.0",
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^1.7.7",
    "chart.js": "^4.4.4",
    "firebase": "^10.13.1",
    "materialize-css": "^1.0.0-rc.2",
    "moment": "^2.30.1",
    "pako": "^2.1.0",
    "react": "^18.3.1",
    "react-big-calendar": "^1.15.0",
    "react-calendar": "^5.0.0",
    "react-chartjs-2": "^5.2.0",
    "react-dom": "^18.3.1",
    "react-plaid-link": "^3.6.0",
    "react-router-dom": "^6.26.2",
    "react-script": "^2.0.5",
    "react-scripts": "^3.4.4",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not op_mini all"
  ],
  "devDependencies": {
    "@babel/compat-data": "7.19.4",
    "@babel/core": "^7.19.6",
    "@babel/generator": "7.19.6",
    "@babel/helper-compilation-targets": "7.19.3",
    "@babel/helper-create-class-features-plugin": "7.19.0",
    "@babel/helper-module-transforms": "7.19.6",
    "@babel/plugin-proposal-class-properties": "^7.18.6",
    "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
    "@babel/plugin-proposal-optional-chaining": "^7.21.0",
    "@babel/plugin-proposal-private-methods": "^7.18.6",
    "@babel/plugin-transform-private-property-in-object": "^7.24.7",
    "@babel/preset-env": "^7.26.0",
    "@babel/preset-react": "^7.25.9",
    "customize-cra": "^1.0.0",
    "react-app-rewired": "^2.2.1"
  }
}


Already tried upgrading my webpack version but got an error saying to downgrade.

Appwrite: Image Preview Not Working Despite Valid File IDs

I’m using Appwrite for my project and have implemented a service to upload images and retrieve their previews. The image IDs are correctly stored in my database after uploading, but when I attempt to fetch the image preview, it returns an undefined URL.

Here’s a brief overview of my implementation:

  1. Uploading Images: I upload images to Appwrite storage using the
    following method:
async uploadFile(file) {
    if (!(file instanceof File)) {
        throw new Error("Invalid file type.");
    }

    try {
        return await this.bucket.createFile(
            conf.appwriteListingImagesBucketId,
            ID.unique(),
            file
        );
    } catch (error) {
        console.error("Appwrite service :: uploadFile() :: ", error);
        throw new Error("Failed to upload file.");
    }
}
  1. Fetching Image Preview: I attempt to get the preview using this
    method:
async getFilePreview(fileId) {
    if (!fileId) {
        throw new Error("File ID is required.");
    }

    try {
        const result = await this.bucket.getFilePreview(
            conf.appwriteListingImagesBucketId,
            fileId,
            1800, // width
            0, // height (ignored when 0)
            "center", // crop center
            "90", // compression
            5, // border width
            "CDCA30", // border color
            15, // border radius
            1, // full opacity
            0, // no rotation
            "FFFFFF", // background color
            "jpg" // output format
        );

        return result.href; // Return the URL for the image preview
    } catch (error) {
        console.error("Error fetching file preview:", error);
        throw new Error("Failed to fetch file preview.");
    }
}
  1. Using the Service: In my React component, I call getFilePreview like
    this:
useEffect(() => {
    const fetchPreviewUrl = async () => {
        try {
            const url = await listingImageService.getFilePreview(listing.images[0]);
            console.log("url", url);
            setPreviewUrl(url);
        } catch (error) {
            console.error("Error fetching image preview:", error);
        }
    };
    fetchPreviewUrl();
}, []);

Problem:
The listing. images contain a valid file ID.
The console logs indicate that getFilePreview is being called, but the resulting URL is undefined.
I’ve checked that the bucket ID and permissions are correct.
Additional Information:
I’ve tested with various image formats (JPEG, PNG) and ensured that my Appwrite server is running correctly.
Aside from the expected error handling, there are no apparent errors in the console.

Question:
What could be causing the image preview to return an undefined URL? Are there any known issues with Appwrite’s getFilePreview method or specific configurations I should check?

How to iterate the array inside array of object in react js?

I am trying to iterate the data but it saying testData is not iterable.
This is my code –

const testData = details?.[0]?.one?.map((item) => {
    const labelTwo =
      item?.itemType === 'FIRST' ? 'newLabel' : 'oldLabel';
    return {
      label: details?.[0]?.one?.length > 1 ? labelTwo : 'labelOne',
      value: item?.value,
    };
  });
  const myData: Item[] = [
    ...testData,
    {
      label: 'first',
      value: 'firstValue',
    },
    isVisible && {
      label: 'second',
      value: 'secondValue',
    },
  ];
return (
  <>
    {myData?.map((item: Item) => {
      return (
       <div>
        <div>{item?.label}</div>
        <div>{item?.value}</div>
       </div>
      );
    }
  </>
)

Below in return when I am trying to iterate myData using map function then it is saying testData is not iterable.
Am I doing anything wrong ? what will be the best approach here to iterate the data