Express.js Route Returns Null Value for Database Query Using _id Field

I have the following Express.js route

router.post('/', async (req, res) => {
       try {
        const {orderIDs} = req.body;

        for (const orderID of orderIDs) {
            const order = await Purchases.findById(orderID);
            console.log(order)
            const orderData = order.orderData;

            // Update stock Levels
            for (const item of orderData) {
                const product = await Products.findOne({productCode: item.productCode});
                await increaseQuantity(product.quantity, item.quantity, item.productCode);
            }
            // Update Purchases Table
            await updateOrderStatusPurchases(orderID);
            // Update TxnAudit Table
            await updateStatusTXN_AUDIT(orderID);
        }

        res.status(200).json({ message: 'Pending orders received'});
    } catch (error) {
        logger.error(error);
        res.status(500).json({ error: 'An error occurred while canceling orders' });
    }
  });

For some reason, whenever I try to retrieve a particular order from the database using the _id field results in a null value even though the document does exist in the database.

I have tried replacing await Purchases.findById(orderID) with await Purchases.findOne({"_id": orderID) with no luck.

I have also made sure that the Atlas User has the right permissions and that I am connecting to the correct mongodb instance.

Any help will be much appreciated.

Thanks in advance

In angular form is getting submitted without form value

Below Is my html and ts code I have added settimeout for 2seconds to get the response and append to form without which value is not getting appended.
Please provide any alternate solution if we can avoid settiemout here

export class ABCComponent implements OnInit {

  private subscriptions: Subscription[] = [];
  amount: any;
  samlResponse: string | undefined;
  @ViewChild('hiddenForm') hiddenForm: ElementRef | undefined;

 

  ngOnInit(): void {
    const routeSubscription = this.activatedRoute.params.subscribe({
      next: (params: Params) => {
        this.amount = params['val']
      }
    })
    this.subscriptions.push(routeSubscription);
    this.onPageLoad();
  }

  onPageLoad(){
    let payload ={
      "val":this.val
    }
   
    this.service.api(payload).subscribe( {
      next: ((response: any) => {
        this.res = response.res;
       setTimeout(() => {
        this.submitForm();
       }, 2000);
      }),
      error: (value: any) => { 

      }
    }
    )}

    submitForm(){
        this.hiddenForm?.nativeElement.submit();
    }
}
<div class="d-flex align-items-center container-fluid min-vh-100">
<form #hiddenForm method="post" action="example.com"
(ngSubmit)="submitForm()">
    <input type="hidden" [value]="res" name="res">
<button type="submit" style="display: none;">Submit</button>
</form>
<div class="text-center w-100 fs-4"><b>Redirecting...</b></div>
</div>

How to pass javascript array as value for $in of Mongodb query

I currently have a script where I am querying mongo, taking the results and making an array out of part of it and then feeding it back into another query.

So to make the query simple I have something like this.

items=["A","B","C"]
db.test.aggregate([{$match:{name:{$in:items}}}]);

When I manually enter each item into the query it works just fine but if I use the variable I get an empty result back. I tried turning it into a string and also passing it in with [] around it. None worked. Im assuming there is some way to do what I am doing but can’t find a similar question anywhere.

How to parse a local CSV file with react and docusaurus?

I have been trying to implement a graph on a website I am working on and I need to display sensor data. Currently I am using the react-chartjs-2 and a JSON file to display the data. However I was wondering if there is a way to parse a local csv file.

Currently the code I am using is from a different stack overflow question to test the csv file being loaded in.

import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import React from 'react';
import {readString} from 'react-papaparse'
import siteListCSV from './xsensACC.csv'

const papaConfig = {
  complete: (results, file) => {
    console.log('Parsing complete:', results, file);
  },
  download: true,
  error: (error, file) => {
    console.log('Error while parsing:', error, file);
  },
};
readString(siteListCSV, papaConfig);

function App() {
  return (
    <h1>Check the console</h1>
  );
}

export default App;

After running this, I get an error that says

Module parse failed: Unexpected token (1:47)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> PacketCounter,SampleTimeFine,Acc_X,Acc_Y,Acc_Z,,,,,,,
| 0,398532073,0,0,0,,,,,,, 
| 1,398548740,0.0829515159130096,-0.0660160481929779,10.1379995346069,,,,,,,
client (webpack 5.88.2) compiled with 2 errors

So, I followed the link that is supplied and it takes me to the webpack.js website detailing how to implement loaders. However since the project I’m working on uses docusaurus, the closest file I could find to webpack.config.js is docusaurus.config.js.

I then looked at the docusaurus documentation for implementing plugins and have had no success in finding official or community plugins that allow loading in CSV files.

I assume that the error is with loading the csv file rather than parsing it.

Is this a small problem with a solution I overlooked or is this an improbable task?

Thanks

echarts use second x axis in tooltip

I have a chart using echarts that has nested x-axis (2 levels).

For the tooltip I want to show both values of the x-axis, but I cannot figure out how to show the respective value of the second x-axis.
I use this function as a formatter in the tooltip:

formatter: function(params) {
  console.log(params); // for debugging only
  var tooltip = params[0].name + '<br>';  
  for (var i = 0; i < params.length; i++) {  
    tooltip += params[i].marker + params[i].seriesName + ': ' + params[i].value.toFixed(2) + '<br>';  
  }  
  return tooltip;  
}

which results in this tooltip (note that the second X axis corresponding to the age group ‘Teen’ is missing).

enter image description here

What I want to have is something like this

enter image description here

See also echarts demo


var data = [  
  { dominantHand: 'Right', age: 'Teen', value: Math.random(), gender: 'Female' },  
  { dominantHand: 'Right', age: 'Adult', value: Math.random(), gender: 'Female' },  
  { dominantHand: 'Right', age: 'Retired', value: Math.random(), gender: 'Female' },  
  { dominantHand: 'Left', age: 'Teen', value: Math.random(), gender: 'Female' },  
  { dominantHand: 'Left', age: 'Adult', value: Math.random(), gender: 'Female' },  
  { dominantHand: 'Left', age: 'Retired', value: Math.random(), gender: 'Female' },   
  { dominantHand: 'Right', age: 'Teen', value: Math.random(), gender: 'Male' },  
  { dominantHand: 'Right', age: 'Adult', value: Math.random(), gender: 'Male' },  
  { dominantHand: 'Right', age: 'Retired', value: Math.random(), gender: 'Male' },  
  { dominantHand: 'Left', age: 'Teen', value: Math.random(), gender: 'Male' },  
  { dominantHand: 'Left', age: 'Adult', value: Math.random(), gender: 'Male' },  
  { dominantHand: 'Left', age: 'Retired', value: Math.random(), gender: 'Male' },  
];

option = {
  title: {
    text: 'Fake Values for Dominant Hand and Age',
  },
  tooltip: {
    trigger: 'axis',
    formatter: function(params) {
      console.log(params); // for debugging only
      var tooltip = params[0].name + '<br>';  
      for (var i = 0; i < params.length; i++) {  
        tooltip += params[i].marker + params[i].seriesName + ': ' + params[i].value.toFixed(2) + '<br>';  
      }  
      return tooltip;  
    }
  },
  legend: {
    data: ['Female', "Male"]
  },
  xAxis: [
    {  
      type: 'category',  
      data: ['Right', 'Left', 'Right', 'Left', 'Right', 'Left'],  
      axisLabel: {  
        interval: 0,  
        rotate: 0,  
      },  
    },  
    {  
      type: 'category',  
      data: ['Teen', 'Adult', 'Retired'],  
      axisLabel: {  
        interval: 0,  
        rotate: 0,  
      },  
      position: 'bottom',  
      offset: 30,  
    },
  ],
  yAxis: [
    {
      type: 'value'
    }
  ],
  series: [
    {
      name: 'Female',
      type: 'bar',
      data: data.filter(function(item) {return item.gender === 'Female';}).map(function(item) {return item.value;})
    },
    {
      name: 'Male',
      type: 'bar',
      data:  data.filter(function(item) {return item.gender === 'Male';}).map(function(item) {return item.value;})
    }
  ]
};

How do i link a .ejs file to another .ejs file

I am trying to link my cart.ejs file to my index.ejs file but every time i open the server and click on cart i get cannot get/cart

tried changing the link href on my index.ejs file to be like
<li><a href="cart">Cart</a></li> but still not able to link and open cart via the nav bar on my index.ejs file

Discrepance between an array response from graphQL and same array printed with a console log

I have a very strange behaviour and I need your help.
I retrieve a list of content from a GraphQl API that i attach you:

client.query({query: PAGES_LIST}).then(res => console.log(res.data.pages)

The problem is that the response from the network is that:

[
    {
        "id": "ddf",
        "title": "DDF",
        "type": "HOME",
        "draft": false,
        "newtonId": "64edfc8f3508bb20a9dbef19",
        "creationDate": "2023-08-29 14:11:27",
        "updatedDate": "2023-08-29 14:18:24",
        "__typename": "Page"
    },
    {
        "id": "home",
        "title": "Aujourd'hui",
        "type": "HOME",
        "draft": false,
        "newtonId": "649f004bdd86676fc0b4fb7e",
        "creationDate": "2023-06-30 16:18:19",
        "updatedDate": "2023-06-30 16:18:19",
        "__typename": "Page"
    },
    {
        "id": "home",
        "title": "Aujourd'hui",
        "type": "HOME",
        "draft": true,
        "newtonId": "64e4694ede8dac1164feabd4",
        "creationDate": "2023-08-22 07:52:46",
        "updatedDate": "2023-10-31 10:35:26",
        "__typename": "Page"
    },
    {
        "id": "newpage",
        "title": "New Page",
        "type": "HOME",
        "draft": true,
        "newtonId": "6540db14d9696820b319a6af",
        "creationDate": "2023-10-31 10:46:44",
        "updatedDate": "2023-10-31 10:46:44",
        "__typename": "Page"
    }
]

And the console.log from the client side is that. As you could see the item with the same id “home” is the same now:

[
    {
        "__typename": "Page",
        "id": "ddf",
        "title": "DDF",
        "type": "HOME",
        "draft": false,
        "newtonId": "64edfc8f3508bb20a9dbef19",
        "creationDate": "2023-08-29 14:11:27",
        "updatedDate": "2023-08-29 14:18:24"
    },
    {
        "__typename": "Page",
        "id": "home",
        "title": "Aujourd'hui",
        "type": "HOME",
        "draft": false,
        "newtonId": "649f004bdd86676fc0b4fb7e",
        "creationDate": "2023-06-30 16:18:19",
        "updatedDate": "2023-06-30 16:18:19"
    },
    {
        "__typename": "Page",
        "id": "home",
        "title": "Aujourd'hui",
        "type": "HOME",
        "draft": false,
        "newtonId": "649f004bdd86676fc0b4fb7e",
        "creationDate": "2023-06-30 16:18:19",
        "updatedDate": "2023-06-30 16:18:19"
    },
    {
        "__typename": "Page",
        "id": "newpage",
        "title": "New Page",
        "type": "HOME",
        "draft": true,
        "newtonId": "6540db14d9696820b319a6af",
        "creationDate": "2023-10-31 10:46:44",
        "updatedDate": "2023-10-31 10:46:44"
    }
]

How is it possibile and could I solve it ?

I excpect to see the same array that the newtowrk provides me.

Google Chrome extension – how to overlay a map on the webpage by another map layer?

I would like to create an extension for Google Chrome. I am trying to overlay the map for Garmin Connect sports activities. Because there are only two possibilities to choose – Google map or OpenStreet map. But I would like to use another one, more detailed map.
Please, could somebody give an example of code how to overlay a map with another map? As far as I know, it should be in JavaScript (because of the Chrome web browser extension).
Thanks for advice!

I would like to create Google Chrome extension for overlaying map on server Garmin Connect.

Images not loading on web page

I am trying to display some images on my webpage using node js express and hbs file the image is not being displayed on web page getting error GET http://localhost:3000/tempelates/P2.jpg 404 (Not Found)

.hbs code –

<!DOCTYPE html>
<html>
<head>
    <title>ParkEase - Parking Management System</title>
    <style>
        /* Your CSS styles here */
        body {
            font-family: Arial, sans-serif;
            background-color: #f2f2f2;
        }
        .header {
            text-align: center;
            padding: 20px 0;
            background-color: #4CAF50;
            color: #ffffff;
        }
        .container {
            width: 90%;
            margin: 20px auto;
            display: flex;
            flex-wrap: wrap;
            justify-content: space-between;
        }
        .row {
            width: 100%;
            display: flex;
            justify-content: space-between;
        }
        .parking-container {
            width: 30%;
            margin-bottom: 30px;
            border: 1px solid #ccc;
            border-radius: 5px;
            padding: 10px;
            background-color: #ffffff;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            cursor: pointer; /* Add cursor style to indicate it's clickable */
        }
        .parking-container img {
            width: 100%;
            border-radius: 5px;
            margin-bottom: 10px;
        }
        .parking-info {
            text-align: left;
        }
        .time-period {
            text-align: left;
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <div class="header">
        <h1>ParkEase - Parking Management System</h1>
    </div>
    <div class="container">
        <div class="row">
            <div class="parking-container" onclick="promptRent('Parking 1', '1')">
                <img src="pexels-abdulwahab-alawadhi-3422964.jpg" alt="Parking 1">
                <div class="parking-info">
                    <h3>Parking spot - 1</h3>
                    <p>Parking: P1</p>
                </div>
            </div>
            <div class="parking-container" onclick="promptRent('Parking 2', '2')">
                <img src="/tempelates/P2.jpg" alt="Parking 2">
                <div class="parking-info">
                    <h3>Parking spot - 2</h3>
                    <p>Parking: P2</p>
                </div>
            </div>
            <div class="parking-container" onclick="promptRent('Parking 3', '3')">
                <img src="/tempelates/P3.jpg" alt="Parking 3">
                <div class="parking-info">
                    <h3>Parking spot - 3</h3>
                    <p>Parking: P3</p>
                </div>
            </div>
        </div>
    </div>

    <script>
        function promptRent(parking, parkingSpot) {
    var vehicleNumber = prompt("Enter Vehicle Number:");
    if (vehicleNumber) {
        var daysCount = prompt("Enter the number of days for parking:");
        if (daysCount) {
            var totalCost = 100 * daysCount; // Assuming the cost per day is $100

            // Calculate rental start time (current time)
            var rentalStartTime = new Date();
            var rentalStartFormatted = formatDateTime(rentalStartTime);
            
            // Calculate rental end time by adding the specified number of days to the start time
            rentalStartTime.setDate(rentalStartTime.getDate() + parseInt(daysCount));
            var rentalEndFormatted = formatDateTime(rentalStartTime);

            // Print the receipt with rental start and end times, including the date and time
            alert("ReceiptnnParking: " + parking + "nVehicle Number: " + vehicleNumber + "nParking Spot: " + parkingSpot + "nRental Start: " + rentalStartFormatted + "nRental End: " + rentalEndFormatted + "nTotal Cost: $" + totalCost);
        }
    }
}

function formatDateTime(date) {
    var dd = String(date.getDate()).padStart(2, '0');
    var mm = String(date.getMonth() + 1).padStart(2, '0'); // January is 0!
    var yyyy = date.getFullYear();
    var hours = String(date.getHours()).padStart(2, '0');
    var minutes = String(date.getMinutes()).padStart(2, '0');
    var seconds = String(date.getSeconds()).padStart(2, '0');

    return mm + '/' + dd + '/' + yyyy + ' ' + hours + ':' + minutes + ':' + seconds;
}


    </script>
</body>
</html>

.js code –

const express=require("express")
const app=express()
const path=require("path")
const hbs=require("hbs")
const collection=require("./mongodb")

const tempelatePath=path.join(__dirname, '../tempelates')

app.use(express.static(path.join(__dirname, '../tempelates')));

app.use(express.json())
app.set("view engine", "hbs")
app.set("views", tempelatePath)
app.use(express.urlencoded({extended:false}))

app.get("/",(req, res) => {
    res.render("login")
})

app.get("/signup",(req, res) => {
    res.render("signup")
})

app.post("/signup", async (req, res) => {
  const data={
      name:req.body.name,
      password:req.body.password
  }

await collection.insertMany([data])

res.render("login")

})


app.post("/login", async (req, res) => {
    
  try{
      const check=await collection.findOne({name:req.body.name})

      if(check.password===req.body.password){
          res.render("home")
      }
      else{
          res.send("wrong password")
      }


  }
  catch{
    res.send("Wrong details")
  }
  
  })
  
app.listen(3000,() => {
    console.log("port connected");
})

the three images P1.jpg P2.jpg P3.jpg is not being displayed instead icon is being displayed

tried diiferent things

Error when using WOWJS in a React project. Uncaught TypeError: Cannot set properties of undefined (setting ‘getPropertyValue’)

ERORR element does not receive animation

Hi all) I have an error when using WOWJS in a React project.Uncaught TypeError: Cannot set properties of undefined (setting ‘getPropertyValue’). Tried to find the answer to this question but never found it. I tried installing WOW.JS instead of WOWJS, but it didn’t help. The project was created with Vite.

`

import { useEffect, useState } from "react";
import WOW from "wowjs"
import "animate.css";

import Modal from "../modalCalc/  Modal";

const OurWorks = ({ data }) => {
  const [modal, setModal] = useState(false);
  const [moadalPicture, setModalPicture] = useState(null);

  const onHandleClick = (e) => {
    e.preventDefault();
    setModalPicture(e.target.src);
    setModal(true);
  };

  const result = (arr) =>
    arr.map((item, index) => {
      console.log(`Animating element ${index}:`, item);
      return (
        <div
          key={index}
          className="col-lg-3 col-md-4 col-sm-6 col-xs-12 text-center wow animate__fadeInUp"
          data-wow-delay={index === 0 ? "0s" : `${0.1 * index}s`}
        >
          <a onClick={onHandleClick} href={item.a}>
            <img className="preview" src={item.img} alt="window" />
          </a>
        </div>
      );
    });
    useEffect(() => {
      console.log("WOW.JS initialized");
      new WOW.WOW({
        live: false,
      }).init();
    }, []);



  return (
    <section className="works">
      <div className="container">
        <div className="section_headaer">
          <h2 style={{ display: "flex", justifyContent: "center" }}>
            Our Works
          </h2>
          <div className="section_header_sub"></div>
        </div>
        <div className="row">{result(data)} </div>
        {modal ? (
          <Modal
            modalClose={() => setModal(false)}
            inlineStyle={{ width: "70%", height: "90%" }}
          >
            <img
              className="preview"
              src={moadalPicture}
              alt="window"
              style={{ height: "80%" }}
            />
          </Modal>
        ) : null}
      </div>
    </section>
  );
};

export default OurWorks;

[[ERORR](https://i.stack.imgur.com/ydDoi.png)](https://i.stack.imgur.com/FPJ3N.png)

I tried installing WOW.JS instead of WOWJS, but it didn’t help.

How to add new field based on sum of previous documents that comes before every document in Mongoose?

When a collection is sorted by date, I am trying to add a new field to every document based on values of previous documents that comes before the document. Context is that I am trying to create a line graph out of entries so I need the current sum for every entry.

Example is like this:

Input:
Collection:

Document-1: { type: 'typeX', date: '01-01-2000', value: 10 }
Document-2: { type: 'typeY', date: '01-03-2000', value: -5 }
Document-3: { type: 'typeX', date: '01-02-2000', value: 3 }
Document-4: { type: 'typeX', date: '01-03-2000', value: -1 }
Document-5: { type: 'typeY', date: '01-01-2000', value: 10 }

Output:
{ type: 'typeX', date: '01-01-2000', value: 10, sum: 10}
{ type: 'typeY', date: '01-01-2000', value: 10, sum: 10}
{ type: 'typeX', date: '01-02-2000', value: 3, sum: 13}
{ type: 'typeY', date: '01-03-2000', value: -5, sum: 5}
{ type: 'typeX', date: '01-03-2000', value: -1, sum: 12}

IS this possible with aggregate or any other way in Mongoose?

Is this an intentional design on object destructuring: the assignment result differs as whether the value to be assigned is an object literal or not

I always have such a intuition that an expression inside code can be mentally substituted by its evaluation result. However, the following two code snippets have different execution results.

let obj = {};
({a: obj.b, b: obj.a} = {a: 1, b: 2});
console.log(obj); // {b: 1, a: 2}
let obj = {a: 1, b: 2};
({a: obj.b, b: obj.a} = obj);
console.log(obj); // {a: 1, b: 1}

Is this an intentional design?

What is the difference of async and not async fcuntion in listening websocket Javascript

With async function in Websocket:

import WebSocket from "ws"

const ws = new WebSocket(`example_url`)
ws.on("message", async function message(data) {console.log(data)})

Without async function in Websocket:

ws.on("message", function message(data) {console.log(data)})

Is there any difference between these two?

Will the data transmission speed become faster because of using async function? Or only add async when I need to use the asynchronous function like await inside the function?

How can I send cookie to the client so that the session_id I am sending will be exclusive for that Website?

I have this clients like 10.10.210.210/myApp1 and 10.10.210.210/myApp2. These 2 apps call common APIs.I have this login API for these apps like 10.10.210.210/live/login and other APIs as 10.10.210.210./live/xyz.
We are sending session_id cookie in the response of login API so that we can use that to authenticate for other APIs. But if I am opening these 2 client apps together on 2 different tabs of browser, session_id cookie is getting overwritten for them by each other.

I have tried adding few checks in PATH and DOMAIN attribute of cookie header but nothing worked.

Can You please suggest what can I do to distinguish these 2 session_id cookies.

Changing 1 on 1 webRTC Ably API code to handle group voice call

Right now I have a fully working 1 on 1 voice call using webRTC and Ably API. I want to modify my code to somehow create one room (I won’t need more than one channel) so when people click to join it they will be able to talk to each other together. Any ideas how to do it?

my ably-videocall.js:

var membersList = []
var connections = {}
var currentCall
var localStream
var constraints = {video: false, audio: { echoCancellation: true}}
var apiKey = '0uLlaA.7H2Oow:P4nF0mGqCpOOmFtxNGPsctl5PGh8uTuCz1HPxf_yIfI'
var clientId = 'client-' + Math.random().toString(36).substr(2, 16)
var realtime = new Ably.Realtime({ key: apiKey, clientId: clientId })
var AblyRealtime = realtime.channels.get('ChatChannel')

AblyRealtime.presence.subscribe('enter', function(member) {
    AblyRealtime.presence.get((err, members) => {
        membersList = members
        renderMembers()
    })
})
AblyRealtime.presence.subscribe('leave', member => {
    AblyRealtime.presence.get((err, members) => {
        membersList = members
        renderMembers()
    })
})
AblyRealtime.presence.enter()

function renderMembers() {
    var list = document.getElementById('memberList')
    var online = document.getElementById('online')
    online.innerHTML = 'Users online (' + (membersList.length === 0 ? 0 : membersList.length - 1) + ')'
    var html = ''
    if (membersList.length === 1) {
        html += '<li> No member online </li>'
        list.innerHTML = html
        return
    }
    for (var index = 0; index < membersList.length; index++) {
        var element = membersList[index]
        if (element.clientId !== clientId) {
            html += '<li><small>' + element.clientId + ' <button class="btn btn-xs btn-success" onclick=call("' + element.clientId + '")>call now</button> </small></li>'
        }
    }
    list.innerHTML = html
}
function call(client_id) {
    if (client_id === clientId) return
    alert(`attempting to call ${client_id}`)
    AblyRealtime.publish(`incoming-call/${client_id}`, {
            user: clientId
        })
}
AblyRealtime.subscribe(`incoming-call/${clientId}`, call => {
    if (currentCall != undefined) {
        // user is on another call
        AblyRealtime.publish(`call-details/${call.data.user}`, {
            user: clientId,
            msg: 'User is on another call'
        })
        return
    }
    var isAccepted = confirm(`You have a call from ${call.data.user}, do you want to accept?`)
    if (!isAccepted) {
        // user rejected the call
        AblyRealtime.publish(`call-details/${call.data.user}`, {
            user: clientId,
            msg: 'User declined the call'
        })
        return
    }
    currentCall = call.data.user
    AblyRealtime.publish(`call-details/${call.data.user}`, {
        user: clientId,
        accepted: true
    })
})
AblyRealtime.subscribe(`call-details/${clientId}`, call => {
    if (call.data.accepted) {
        initiateCall(call.data.user)
    } else {
        alert(call.data.msg)
    }
})
function initiateCall(client_id) {
    navigator.mediaDevices.getUserMedia(constraints)
        .then(function(stream) {
            /* use the stream */
            localStream = stream
            localStream.getAudioTracks().forEach(track => {
                track.enabled = true; // Ensure the track is enabled
                track.volume = 0; // Set volume to zero
            });
                // Create a new connection
            currentCall = client_id
            if (!connections[client_id]) {
                connections[client_id] = new Connection(client_id, AblyRealtime, true, stream)
            }
            document.getElementById('call').style.display = 'block'
        })
        .catch(function(err) {
            /* handle the error */
            alert('Could not get video stream from source')
        })
}
AblyRealtime.subscribe(`rtc-signal/${clientId}`, msg => {
    if (localStream === undefined) {
        navigator.mediaDevices.getUserMedia(constraints)
            .then(function(stream) {
                /* use the stream */
                localStream = stream
                localStream.getAudioTracks().forEach(track => {
                track.enabled = true; // Ensure the track is enabled
                track.volume = 0; // Set volume to zero
            });
                connect(msg.data, stream)
            })
            .catch(function(err) {
                alert('error occurred while trying to get stream')
            })
    } else {
        connect(msg.data, localStream)
    }
})
function connect(data, stream) {
    if (!connections[data.user]) {
        connections[data.user] = new Connection(data.user, AblyRealtime, false, stream)
    }
    connections[data.user].handleSignal(data.signal)
    document.getElementById('call').style.display = 'block'
}
function receiveStream(client_id, stream) {
    var audio = new Audio();
            audio.srcObject = stream;
            audio.play();
    renderMembers()
}
function handleEndCall(client_id = null) {
    if (client_id && client_id != currentCall) {
        return
    }
    client_id = currentCall;
    alert('call ended')
    currentCall = undefined
    connections[client_id].destroy()
    delete connections[client_id]
    for (var track of localStream.getTracks()) {
        track.stop()
    }
    localStream = undefined
    document.getElementById('call').style.display = 'none'
}

my Connection class:

class Connection {
    constructor(remoteClient, AblyRealtime, initiator, stream) {
        console.log(`Opening connection to ${remoteClient}`)
        this._remoteClient = remoteClient
        this.isConnected = false
        this._p2pConnection = new SimplePeer({
            initiator: initiator,
            stream: stream
        })
        this._p2pConnection.on('signal', this._onSignal.bind(this))
        this._p2pConnection.on('error', this._onError.bind(this))
        this._p2pConnection.on('connect', this._onConnect.bind(this))
        this._p2pConnection.on('close', this._onClose.bind(this))
        this._p2pConnection.on('stream', this._onStream.bind(this))
    }
    handleSignal(signal) {
        this._p2pConnection.signal(signal)
    }
    send(msg) {
        this._p2pConnection.send(msg)
    }
    destroy() {
        this._p2pConnection.destroy()
    }
    _onSignal(signal) {
        AblyRealtime.publish(`rtc-signal/${this._remoteClient}`, {
            user: clientId,
            signal: signal
        })
    }
    _onConnect() {
        this.isConnected = true
        console.log('connected to ' + this._remoteClient)
    }
    _onClose() {
        console.log(`connection to ${this._remoteClient} closed`)
        handleEndCall(this._remoteClient)
    }
    _onStream(data) {
        receiveStream(this._remoteClient, data)
    }
    _onError(error) {
        console.log(`an error occurred ${error.toString()}`)
    }
}