Group Array Object nested object by key and Iterate Through Them

I have an array object with nested objects inside. In each object of the array object is a nested object, i want to do the following:

  1. Iterate through the testInfo property of the participantDetails property of the testObj arrayObject.

  2. I want to create or get another object by using the JavaScript Object reduce function to group the Agency property of the participantDetails of participants property of the testObj array object.

I have written and edited my codes but couldn’t get this right. Below are my code:

const testObj = [{
    id: 1,
    testName: 'Contingent/20sw',      
    testTest: 125,
    startDate: '19-10-2024',
    endDate: '21-11-2024',
    testCenter: 'Onne',
    participants:{     
      participantDetails: {       
          id: 1,     
          agency: 'Farehnsic Enterprise',
      agencyPhone: '07083590156',
      agencyAltPhone: '07083590156',
      agencyEmail: '[email protected]',
      testTest: 25,
      testInfo:[{
        courseNo: '690638HS738/51YG',
        centerAddress: '22, Muri Okunola Road, VI-Lagos, Nigeria',
    },    
    {
        courseNo: '389474RY738/51YG',
        centerAddress: '33, Dangote Lane, Apapa-Lagos, Nigeria',            
    },    
    {
        courseNo: '93788NB738/51YG',
        centerAddress: '11, Harley Grace Drive, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '490259FU003/51YG',
        centerAddress: '8, Martin Dell Road, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '846708GH462/51YG',
        centerAddress: '1, Adeola Orlean Road, VI-Lagos, Nigeria',            
    }],
  },    
      participantDetails: {
          id: 2,
          agency: 'Platinum Logistics',
      agencyPhone: '07083590156',
      agencyAltPhone: '07083590156',
      agencyEmail: '[email protected]',
      testTest: 35,
      testInfo:[{
        courseNo: '690638HS738/51YG',
        centerAddress: '22, Muri Okunola Road, VI-Lagos, Nigeria',
    },    
    {
        courseNo: '389474RY738/51YG',
        centerAddress: '33, Dangote Lane, Apapa-Lagos, Nigeria',            
    },    
    {
        courseNo: '93788NB738/51YG',
        centerAddress: '11, Harley Grace Drive, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '490259FU003/51YG',
        centerAddress: '8, Martin Dell Road, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '846708GH462/51YG',
        centerAddress: '1, Adeola Orlean Road, VI-Lagos, Nigeria',            
    }],
  },    
      participantDetails: {
          id: 3,
          agency: 'Chevron PLC',
      agencyPhone: '07083590156',
      agencyAltPhone: '07083590156',
      agencyEmail: '[email protected]',
      testTest: 35,
      testInfo:[{
        courseNo: '690638HS738/51YG',
        centerAddress: '22, Muri Okunola Road, VI-Lagos, Nigeria',
    },    
    {
        courseNo: '389474RY738/51YG',
        centerAddress: '33, Dangote Lane, Apapa-Lagos, Nigeria',            
    },    
    {
        courseNo: '93788NB738/51YG',
        centerAddress: '11, Harley Grace Drive, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '490259FU003/51YG',
        centerAddress: '8, Martin Dell Road, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '846708GH462/51YG',
        centerAddress: '1, Adeola Orlean Road, VI-Lagos, Nigeria',            
    }],
  },    
      participantDetails: {
          id: 4,
          agency: 'Glasgow Investment',
      agencyPhone: '07083590156',
      agencyAltPhone: '07083590156',
      agencyEmail: '[email protected]',
      testTest: 35,
      testInfo:[{
        courseNo: '690638HS738/51YG',
        centerAddress: '22, Muri Okunola Road, VI-Lagos, Nigeria',
    },    
    {
        courseNo: '389474RY738/51YG',
        centerAddress: '33, Dangote Lane, Apapa-Lagos, Nigeria',            
    },    
    {
        courseNo: '93788NB738/51YG',
        centerAddress: '11, Harley Grace Drive, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '490259FU003/51YG',
        centerAddress: '8, Martin Dell Road, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '846708GH462/51YG',
        centerAddress: '1, Adeola Orlean Road, VI-Lagos, Nigeria',            
    }],
  },    
      participantDetails: {
          id: 5,
          agency: 'Actual I.T Solutions',
      agencyPhone: '07083590156',
      agencyAltPhone: '07083590156',
      agencyEmail: '[email protected]',
      testTest: 35,
      testInfo:[{
        courseNo: '690638HS738/51YG',
        centerAddress: '22, Muri Okunola Road, VI-Lagos, Nigeria',
    },    
    {
        courseNo: '389474RY738/51YG',
        centerAddress: '33, Dangote Lane, Apapa-Lagos, Nigeria',            
    },    
    {
        courseNo: '93788NB738/51YG',
        centerAddress: '11, Harley Grace Drive, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '490259FU003/51YG',
        centerAddress: '8, Martin Dell Road, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '846708GH462/51YG',
        centerAddress: '1, Adeola Orlean Road, VI-Lagos, Nigeria',            
    }],
  },    
      participantDetails: {
          id: 6,
          agency: 'Oracle Inc.',
      agencyPhone: '07083590156',
      agencyAltPhone: '07083590156',
      agencyEmail: '[email protected]',
      testTest: 35,
      testInfo:[{
        courseNo: '690638HS738/51YG',
        centerAddress: '22, Muri Okunola Road, VI-Lagos, Nigeria',
    },    
    {
        courseNo: '389474RY738/51YG',
        centerAddress: '33, Dangote Lane, Apapa-Lagos, Nigeria',            
    },    
    {
        courseNo: '93788NB738/51YG',
        centerAddress: '11, Harley Grace Drive, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '490259FU003/51YG',
        centerAddress: '8, Martin Dell Road, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '846708GH462/51YG',
        centerAddress: '1, Adeola Orlean Road, VI-Lagos, Nigeria',            
    }],
  },
      
      participantDetails: {
          id: 7,
          agency: 'Oracle Inc.',
      agencyPhone: '07083590156',
      agencyAltPhone: '07083590156',
      agencyEmail: '[email protected]',
      testTest: 35,
      testInfo:[{
        courseNo: '690638HS738/51YG',
        centerAddress: '22, Muri Okunola Road, VI-Lagos, Nigeria',
    },    
    {
        courseNo: '389474RY738/51YG',
        centerAddress: '33, Dangote Lane, Apapa-Lagos, Nigeria',            
    },    
    {
        courseNo: '93788NB738/51YG',
        centerAddress: '11, Harley Grace Drive, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '490259FU003/51YG',
        centerAddress: '8, Martin Dell Road, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '846708GH462/51YG',
        centerAddress: '1, Adeola Orlean Road, VI-Lagos, Nigeria',            
    }],
  },
      participantDetails: {
          id: 8,
          agency: 'Pinquest Ventures',
      agencyPhone: '07083590156',
      agencyAltPhone: '07083590156',
      agencyEmail: '[email protected]',
      testTest: 35,
      testInfo:[{
        courseNo: '690638HS738/51YG',
        centerAddress: '22, Muri Okunola Road, VI-Lagos, Nigeria',
    },    
    {
        courseNo: '389474RY738/51YG',
        centerAddress: '33, Dangote Lane, Apapa-Lagos, Nigeria',            
    },    
    {
        courseNo: '93788NB738/51YG',
        centerAddress: '11, Harley Grace Drive, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '490259FU003/51YG',
        centerAddress: '8, Martin Dell Road, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '846708GH462/51YG',
        centerAddress: '1, Adeola Orlean Road, VI-Lagos, Nigeria',            
    }],
  },
      participantDetails: {
          id: 9,
          agency: 'Antiochist Enterprise',
      agencyPhone: '07083590156',
      agencyAltPhone: '07083590156',
      agencyEmail: '[email protected]',
      testTest: 35,
      testInfo:[{
        courseNo: '690638HS738/51YG',
        centerAddress: '22, Muri Okunola Road, VI-Lagos, Nigeria',
    },    
    {
        courseNo: '389474RY738/51YG',
        centerAddress: '33, Dangote Lane, Apapa-Lagos, Nigeria',            
    },    
    {
        courseNo: '93788NB738/51YG',
        centerAddress: '11, Harley Grace Drive, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '490259FU003/51YG',
        centerAddress: '8, Martin Dell Road, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '846708GH462/51YG',
        centerAddress: '1, Adeola Orlean Road, VI-Lagos, Nigeria',            
    }],
  },
      participantDetails: {
          id: 10,
          agency: 'Quantify Inc.',
      agencyPhone: '07083590156',
      agencyAltPhone: '07083590156',
      agencyEmail: '[email protected]',
      testTest: 35,
      testInfo:[{
        courseNo: '690638HS738/51YG',
        centerAddress: '22, Muri Okunola Road, VI-Lagos, Nigeria',
    },    
    {
        courseNo: '389474RY738/51YG',
        centerAddress: '33, Dangote Lane, Apapa-Lagos, Nigeria',            
    },    
    {
        courseNo: '93788NB738/51YG',
        centerAddress: '11, Harley Grace Drive, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '490259FU003/51YG',
        centerAddress: '8, Martin Dell Road, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '846708GH462/51YG',
        centerAddress: '1, Adeola Orlean Road, VI-Lagos, Nigeria',            
    }],
  },
      participantDetails: {
          id: 11,
          agency: 'Apple Inc.',
      agencyPhone: '07083590156',
      agencyAltPhone: '07083590156',
      agencyEmail: '[email protected]',
      testTest: 35,
      testInfo:[{
        courseNo: '690638HS738/51YG',
        centerAddress: '22, Muri Okunola Road, VI-Lagos, Nigeria',
    },    
    {
        courseNo: '389474RY738/51YG',
        centerAddress: '33, Dangote Lane, Apapa-Lagos, Nigeria',            
    },    
    {
        courseNo: '93788NB738/51YG',
        centerAddress: '11, Harley Grace Drive, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '490259FU003/51YG',
        centerAddress: '8, Martin Dell Road, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '846708GH462/51YG',
        centerAddress: '1, Adeola Orlean Road, VI-Lagos, Nigeria',            
    }],
  },
      participantDetails: {
          id: 12,
          agency: 'Datagin Inc.',
      agencyPhone: '07083590156',
      agencyAltPhone: '07083590156',
      agencyEmail: '[email protected]',
      testTest: 35,
      testInfo:[{
        courseNo: '690638HS738/51YG',
        centerAddress: '22, Muri Okunola Road, VI-Lagos, Nigeria',
    },    
    {
        courseNo: '389474RY738/51YG',
        centerAddress: '33, Dangote Lane, Apapa-Lagos, Nigeria',            
    },    
    {
        courseNo: '93788NB738/51YG',
        centerAddress: '11, Harley Grace Drive, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '490259FU003/51YG',
        centerAddress: '8, Martin Dell Road, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '846708GH462/51YG',
        centerAddress: '1, Adeola Orlean Road, VI-Lagos, Nigeria',            
    }],
  },
      participantDetails: {
          id: 13,
          agency: 'InfoMix Inc.',
      agencyPhone: '07083590156',
      agencyAltPhone: '07083590156',
      agencyEmail: '[email protected]',
      testTest: 35,
      testInfo:[{
        courseNo: '690638HS738/51YG',
        centerAddress: '22, Muri Okunola Road, VI-Lagos, Nigeria',
    },    
    {
        courseNo: '389474RY738/51YG',
        centerAddress: '33, Dangote Lane, Apapa-Lagos, Nigeria',            
    },    
    {
        courseNo: '93788NB738/51YG',
        centerAddress: '11, Harley Grace Drive, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '490259FU003/51YG',
        centerAddress: '8, Martin Dell Road, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '846708GH462/51YG',
        centerAddress: '1, Adeola Orlean Road, VI-Lagos, Nigeria',            
    }],
  },
      participantDetails: {
          id: 14,
          agency: 'Sybase Inc.',
      agencyPhone: '07083590156',
      agencyAltPhone: '07083590156',
      agencyEmail: '[email protected]',
      testTest: 35,
      testInfo:[{
        courseNo: '690638HS738/51YG',
        centerAddress: '22, Muri Okunola Road, VI-Lagos, Nigeria',
    },    
    {
        courseNo: '389474RY738/51YG',
        centerAddress: '33, Dangote Lane, Apapa-Lagos, Nigeria',            
    },    
    {
        courseNo: '93788NB738/51YG',
        centerAddress: '11, Harley Grace Drive, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '490259FU003/51YG',
        centerAddress: '8, Martin Dell Road, VI-Lagos, Nigeria',            
    },    
    {
        courseNo: '846708GH462/51YG',
        centerAddress: '1, Adeola Orlean Road, VI-Lagos, Nigeria',            
    }],
  }
    },
    },
  }];

I have tried the following code but it wasn’t giving me what I want. It was complaining of currentValue variable.

const groupedAgencies = testObj.reduce((accumulator, currentValue) => {
    (accumulator[currentValue.testObj.participants.participantDetails.agency] = accumulator[currentValue.testObj.participants.participantDetails.agency] || []).push(currentValue);
}, {});

console.log(`This uses the JS Reduce function to group the record base on a property from the JS object n n The following are Agencies on the TestObj Array Object: n n ${JSON.stringify(groupedAgencies)}`);

What I actually wanted to achieve are the following :

  1. Iterate through the testInfo property of the participantDetails of the Participants property of the testObj arrayObject.

  2. I want to create or get another object by using the JavaScript Object reduce function to group the Agency property of the participantDetails of participants property of the testObj array object.

I can easily do this from the MongoDB using Mongoose but I actually wanted to get the records off the database and use the Javascript to just do the operation at the frontend or the backend(controller) level with just Javascript code so as to release the database or the backend of long running job and allow the backend and database to serve other incoming request easily.

What is the module import order in Typescript?

I have quite simple express server. I am using a self hosted package, so it works the same way as any npm package what it comes to installing and using it. Or at least that’s what I think and how it should work. My actual server file is importing from this package and also imports some route files. My structure is currently roughly like this:

// app.ts
import express from 'express';
import { createWinstonLogger } from 'myown-pkg';
import route1 from './routes/route1';
import route2 from './routes/route2';

const logger = createWinstonLogger(some, params);

const app = express();

app.use('/route1', route1);
app.use('/route2', route2);

export { app, logger }
// routeX.ts
import express from 'express';
import { locallyDefinedAuthMW } from '../mw/auth';

const router = express.Router();

router.get('/someRoute', locallyDefinedAuthMW, ...)

export default router;
// auth.ts
import { logger } from '../app';

export default async (req, res, next) => {
  // some implementation using logger defined in the app file
}

Now this works. However, I want to move the auth middleware (and other stuff) to this separate package, because other services are using the same logic as well. Now that the auth middleware is in the packages I run into some weird import order issue. If I import the authMW in the app file, it is imported correctly. However, if I import it either in the route file or in the auth file, the import is undefined. Any idea why’s that? I have been able to narrow this down so that I am quite sure that this is some kind of module import order issue, but I can’t figure out how to fix it.

// app.ts
import express from 'express';
import { createWinstonLogger, authMW } from 'myown-pkg';
import route1 from './routes/route1';
import route2 from './routes/route2';

console.log(authMW) // <-- shows the function

const logger = createWinstonLogger(some, params);

const app = express();

app.use('/route1', route1);
app.use('/route2', route2);

export { app, logger }
// routeX.ts
import express from 'express';
import { authMW } from 'myown-pkg';

console.log(authMW) // <-- undefined

const router = express.Router();

router.get('/someRoute', locallyDefinedAuthMW, ...)

export default router;
// auth.ts
import { authMW } from 'myown-pkg';
import { logger } from '../app';

console.log(authMW) // <-- undefined

export default async (req, res, next) => {
  // some implementation using logger defined in the app file
}

Has this something to do with the tsconfig, which currently is following:

// tsconfig.json
{
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "target": "ES2020",
    "noImplicitAny": false,
    "strict": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "sourceMap": true,
    "outDir": "dist",
    "baseUrl": ".",
    "skipLibCheck": true
  }
}

JavaScript: How To Use A Variable Or Function In An HTML File After Importing In A main.js File

I am trying to include multiple JS files into one main JS file (called main.js) and include that into my HTML file. One of those JS files have a set of variables (called variables.js) I want to use in my HTML file. I came across using the import/export modules so I tried to put this to use. While I was able to access the variables from variables.js within my main.js file, I am not able to access them in my HTML file. Everytime I run the code, I keep getting the following error:

index.html:38 Uncaught ReferenceError: arrStr1 is not defined at index.html

Below is a code sample of what I am trying to do:

variables.js file

let arrStr1 = ["John", "Doe", "Jane", "Doe", "Michael", "Smith"];

export { arrStr1 };

main.js file

import { arrStr1 } from "./variables.js";

index.html

<script src = "main.js" type = "module"></script>
<script>
console.log(arrStr1);
</script>

Please help me solve this problem. Thank you.

TypeError: Invalid token at 1: https://git.new/pathToRegexpError

i just deployed the project in render and as it says i had to change the path oh backend from localhost to https://chatme-ai.onrender or https://chatme-ai.onrender.com but it keeps giving error about pathToRegexp
C:Usersms077OneDriveDesktopSHUBHAM EXAMShubhamPROJECTSAI-CHATbackendnode_modulespath-to-regexpdistindex.js:85
throw new TypeError(Missing parameter name at ${i}: ${DEBUG_URL});
^

TypeError: Missing parameter name at 1: https://git.new/pathToRegexpError
at name (C:Usersms077OneDriveDesktopSHUBHAM EXAMShubhamPROJECTSAI-CHATbackendnode_modulespath-to-regexpdistindex.js:85:19)
at lexer (C:Usersms077OneDriveDesktopSHUBHAM EXAMShubhamPROJECTSAI-CHATbackendnode_modulespath-to-regexpdistindex.js:103:27)
at lexer.next ()
at Iter.peek (C:Usersms077OneDriveDesktopSHUBHAM EXAMShubhamPROJECTSAI-CHATbackendnode_modulespath-to-regexpdistindex.js:119:38)
at Iter.tryConsume (C:Usersms077OneDriveDesktopSHUBHAM EXAMShubhamPROJECTSAI-CHATbackendnode_modulespath-to-regexpdistindex.js:125:28)
at Iter.text (C:Usersms077OneDriveDesktopSHUBHAM EXAMShubhamPROJECTSAI-CHATbackendnode_modulespath-to-regexpdistindex.js:141:30)
at consume (C:Usersms077OneDriveDesktopSHUBHAM EXAMShubhamPROJECTSAI-CHATbackendnode_modulespath-to-regexpdistindex.js:166:29)
at parse (C:Usersms077OneDriveDesktopSHUBHAM EXAMShubhamPROJECTSAI-CHATbackendnode_modulespath-to-regexpdistindex.js:197:20)
at C:Usersms077OneDriveDesktopSHUBHAM EXAMShubhamPROJECTSAI-CHATbackendnode_modulespath-to-regexpdistindex.js:308:74
at Array.map ()

Node.js v20.15.1
[nodemon] app crashed – waiting for file changes before starting…
npm start gave this

i tried in chatgpt but its not working

i tried to update my node-modules and check the routes still notwroking

How Cypress Handles the Clicks?

This is the HTML code

<div>
<li class="tabLblProperties"><a href="/pw/properties/properties_home.do">Properties</a></li>
</div>

The <a> tag is inside the <li> i.e class="tabLblProperties"
but writing the cypress code simply like this
cy.get('.tabLblProperties').click()
instead of
cy.get('.tabLblProperties a').click()

I am confused how this is working?
Beacuse the anchor tag is in the li the clickable is a tag not the li right? But it is working explain me how this is happening!

How to define spread operator type – TypeScript

I have an interface which defines the function signature of various functions

interface AndroidInterface {
  getXo: () => string | null;
  getOx: () => string | null;
  saveXo: (xo: string) => void;
  saveOx: (ox: string) => void;
  getGaid: () => string | null;
  sendAnalyticsEvents: (
    eventName: string,
    eventProperties: Record<string, unknown>
  ) => void;
  getAppVersionCode: () => number | null;
  getClientId: () => string | null;
  getConfig: () => Record<string, unknown> | null;
  isFirstAppLogin: () => boolean;
  logout: () => void;
  openWhatsapp: (message: string, phone: string) => void;
}

These are basically methods on the androidInterfaceMethods object on window exposed through JS bridge. Meaning:

interface Window{
 androidInterfaceMethods?: AndroidInterface;
}

Now, I have a function that dynamically invokes the methods on the androidInterfaceMethods object. The function is defined and typed as follows:

const invokeAndroidInterface = <K extends keyof AndroidInterface>(
  methodName: K,
  ...args: Parameters<ValmoAndroidInterface[K]>
): ReturnType<AndroidInterface[K]> => {
 
  if (typeof window !== "undefined" && window.androidInterfaceMethods) {
    const method = window.androidInterfaceMethods[methodName];
    if (typeof method === "function") {
        return method(...args);
    }
  }
  return null
}

But strangely, I’m getting a red squiggly underline on method(...args) with the message:

A spread argument must either have a tuple type or be passed to a rest parameter.

I’d ideally not want to assert window.androidInterfaceMethods[methodName]; and would instead want TS to infer the function signature correctly. I tried using type guards, but that didn’t help either.
As an experiment, when I hover over the method variable, the type is AndroidInterface[K] which is as expected. Further to verify, I hardcoded the method name, e,g:
const method = window.androidInterfaceMethods["sendAnalyticsEvents"]; and now the type of the method variable showed (eventName: string, eventProperties: Record<string, unknown>) => void;, but that didn’t solve the issue, but finally when I asserted ...args as AndroidInterface["sendAnalyticsEvents"] it worked as expected.

Alternatively, asserting window.androidInterfaceMethods[methodName] as Function also fixes the issue, but I believe it is not entirely correct.

Could anyone please shed some light here?

d3.js multiple relationship visual / tangled tree => collapsible ? add link to node?

I am trying add some features to following developments without success:
here

I need to keep the multi parent’s relationship.

  1. I’d like to make this tree collapsible first.

  2. Second addition is hyperlinks to the nodes and texts of the node.
    The url are in the data as follwos:

levels => id / parents / url
samples:

const levels = [
  [{ id: 'workplace' , url: 'http://www.google.co.uk' }],
  [
    { id: 'B_01_Dedicated access' , parents: ['workplace'] , url: 'http://www.google.co.uk' },

For the first problem I tried to add and modify following functions:

function collapse(d) {
  if (d.children) {
    d._children = d.children;
    d._children.forEach(collapse);
    d.children = null;
  }
}
function click2(d) {
  if (d.children) {
    d._children = d.children;
    d.children = null;
  } else {
    d.children = d._children;
    d._children = null;
  }
  update(d);
} 

But without success

Note: Staging Ground doesn’t have code snippets, see this. We’re in the process of adding an MRE.

Snippet from linked post: expecting edit.

const margins = {
  top: 20,
  bottom: 300,
  left: 30,
  right: 100,
};

const height = 900;
const width = 900;

const totalWidth = width + margins.left + margins.right;
const totalHeight = height + margins.top + margins.bottom;

const svg = d3.select('body')
  .append('svg')
  .attr('width', totalWidth)
  .attr('height', totalHeight);

const graphGroup = svg.append('g')
  .attr('transform', "translate(" + margins.left + "," + margins.top + ")");

const levels = [
  [{
    id: 'Chaos',
  }],
  [{
    id: 'Gaea',
    parents: ['Chaos'],
  },
    {
      id: 'Uranus',
    },
  ],
  [{
    id: 'Oceanus',
    parents: ['Gaea', 'Uranus'],
  },
    {
      id: 'Thethys',
      parents: ['Gaea', 'Uranus'],
    },
    {
      id: 'Pontus',
    },
    {
      id: 'Rhea',
      parents: ['Gaea', 'Uranus'],
    },
    {
      id: 'Cronus',
      parents: ['Gaea', 'Uranus'],
    },
    {
      id: 'Coeus',
      parents: ['Gaea', 'Uranus'],
    },
    {
      id: 'Phoebe',
      parents: ['Gaea', 'Uranus'],
    },
    {
      id: 'Crius',
      parents: ['Gaea', 'Uranus'],
    },
    {
      id: 'Hyperion',
      parents: ['Gaea', 'Uranus'],
    },
    {
      id: 'Iapetus',
      parents: ['Gaea', 'Uranus'],
    },
    {
      id: 'Thea',
      parents: ['Gaea', 'Uranus'],
    },
    {
      id: 'Themis',
      parents: ['Gaea', 'Uranus'],
    },
    {
      id: 'Mnemosyne',
      parents: ['Gaea', 'Uranus'],
    },
  ],
  [{
    id: 'Doris',
    parents: ['Oceanus', 'Thethys'],
  },
    {
      id: 'Neures',
      parents: ['Pontus', 'Gaea'],
    },
    {
      id: 'Dionne',
    },
    {
      id: 'Demeter',
      parents: ['Rhea', 'Cronus'],
    },
    {
      id: 'Hades',
      parents: ['Rhea', 'Cronus'],
    },
    {
      id: 'Hera',
      parents: ['Rhea', 'Cronus'],
    },
    {
      id: 'Alcmene',
    },
    {
      id: 'Zeus',
      parents: ['Rhea', 'Cronus'],
    },
    {
      id: 'Eris',
    },
    {
      id: 'Leto',
      parents: ['Coeus', 'Phoebe'],
    },
    {
      id: 'Amphitrite',
    },
    {
      id: 'Medusa',
    },
    {
      id: 'Poseidon',
      parents: ['Rhea', 'Cronus'],
    },
    {
      id: 'Hestia',
      parents: ['Rhea', 'Cronus'],
    },
  ],
  [{
    id: 'Thetis',
    parents: ['Doris', 'Neures'],
  },
    {
      id: 'Peleus',
    },
    {
      id: 'Anchises',
    },
    {
      id: 'Adonis',
    },
    {
      id: 'Aphrodite',
      parents: ['Zeus', 'Dionne'],
    },
    {
      id: 'Persephone',
      parents: ['Zeus', 'Demeter'],
    },
    {
      id: 'Ares',
      parents: ['Zeus', 'Hera'],
    },
    {
      id: 'Hephaestus',
      parents: ['Zeus', 'Hera'],
    },
    {
      id: 'Hebe',
      parents: ['Zeus', 'Hera'],
    },
    {
      id: 'Hercules',
      parents: ['Zeus', 'Alcmene'],
    },
    {
      id: 'Megara',
    },
    {
      id: 'Deianira',
    },
    {
      id: 'Eileithya',
      parents: ['Zeus', 'Hera'],
    },
    {
      id: 'Ate',
      parents: ['Zeus', 'Eris'],
    },
    {
      id: 'Leda',
    },
    {
      id: 'Athena',
      parents: ['Zeus'],
    },
    {
      id: 'Apollo',
      parents: ['Zeus', 'Leto'],
    },
    {
      id: 'Artemis',
      parents: ['Zeus', 'Leto'],
    },
    {
      id: 'Triton',
      parents: ['Poseidon', 'Amphitrite'],
    },
    {
      id: 'Pegasus',
      parents: ['Poseidon', 'Medusa'],
    },
    {
      id: 'Orion',
      parents: ['Poseidon'],
    },
    {
      id: 'Polyphemus',
      parents: ['Poseidon'],
    },
  ],
  [{
    id: 'Deidamia',
  },
    {
      id: 'Achilles',
      parents: ['Peleus', 'Thetis'],
    },
    {
      id: 'Creusa',
    },
    {
      id: 'Aeneas',
      parents: ['Anchises', 'Aphrodite'],
    },
    {
      id: 'Lavinia',
    },
    {
      id: 'Eros',
      parents: ['Hephaestus', 'Aphrodite'],
    },
    {
      id: 'Helen',
      parents: ['Leda', 'Zeus'],
    },
    {
      id: 'Menelaus',
    },
    {
      id: 'Polydueces',
      parents: ['Leda', 'Zeus'],
    },
  ],
  [{
    id: 'Andromache',
  },
    {
      id: 'Neoptolemus',
      parents: ['Deidamia', 'Achilles'],
    },
    {
      id: 'Aeneas(2)',
      parents: ['Creusa', 'Aeneas'],
    },
    {
      id: 'Pompilius',
      parents: ['Creusa', 'Aeneas'],
    },
    {
      id: 'Iulus',
      parents: ['Lavinia', 'Aeneas'],
    },
    {
      id: 'Hermione',
      parents: ['Helen', 'Menelaus'],
    },
  ],
];

levels.unshift([]);

// We add one pseudo node to every level to deal with parentless nodes
levels.forEach((l, i) => {
  l.forEach((n, j) => {
    n.level = i;
    if (n.parents !== undefined) {
      n.parent = n.parents[0];
    } else {
      n.parent = `pseudo-${i - 1}`;
    }
  });
  l.unshift({
    id: `pseudo-${i}`,
    parent: i > 0 ? `pseudo-${i - 1}` : "",
    level: i
  });
});

const nodes = levels.flat();
const colours = d3.scaleOrdinal()
  .domain(nodes.filter(n => n.parents)
    .map(n => n.parents.sort()
      .join("-")))
  .range(d3.schemePaired);

function getLinks(nodes) {
  return nodes
    .filter(n => n.data.parents !== undefined)
    .map(n => n.data.parents.map(p => ({
      source: nodes.find(n => n.id === p),
      target: n
    })))
    .flat();
}

const offsetPerPartner = 3;
const drawNodePath = d => {
  const radius = 5;
  // The number of partners determines the node height
  // But when a node has only one partner,
  // treat it the same as when it has zero
  const nPartners = (d.data.partners && d.data.partners.length > 1)
    ? d.data.partners.length
    : 0;

  // We want to centre each node
  const straightLineOffset = (nPartners * offsetPerPartner) / 2;

  const context = d3.path();
  context.moveTo(-radius, 0);
  context.lineTo(-radius, -straightLineOffset);
  context.arc(0, -straightLineOffset, radius, -Math.PI, 0);
  context.lineTo(radius, straightLineOffset);
  context.arc(0, straightLineOffset, radius, 0, Math.PI);
  context.closePath();

  return context + "";
};

const drawLinkCurve = (x0, y0, x1, y1, offset, radius) => {
  const context = d3.path();
  context.moveTo(x0, y0);
  context.lineTo(x1 - 2 * radius - offset, y0);

  // If there is not enough space to draw two corners, reduce the corner radius
  if (Math.abs(y0 - y1) < 2 * radius) {
    radius = Math.abs(y0 - y1) / 2;
  }

  if (y0 < y1) {
    context.arcTo(x1 - offset - radius, y0, x1 - offset - radius, y0 + radius, radius);
    context.lineTo(x1 - offset - radius, y1 - radius);
    context.arcTo(x1 - offset - radius, y1, x1 - offset, y1, radius);
  } else if (y0 > y1) {
    context.arcTo(x1 - offset - radius, y0, x1 - offset - radius, y0 - radius, radius);
    context.lineTo(x1 - offset - radius, y1 + radius);
    context.arcTo(x1 - offset - radius, y1, x1 - offset, y1, radius);
  }
  context.lineTo(x1, y1);
  return context + "";
};

const partnershipsPerLevel = {};
const getPartnershipOffset = (parent, partner) => {
  let partnershipId, level;
  if(partner !== undefined) {
    // On every level, every relationship gets its own offset. If a relationship
    // spans multiple levels, the furthest level is chosen
    level = Math.max(parent.depth, partner.level);
    if(!partnershipsPerLevel[level]) { partnershipsPerLevel[level] = []; }
    partnershipId = [parent.id, partner.id].sort().join("-");
  } else {
    level = parent.depth;
    if(!partnershipsPerLevel[level]) { partnershipsPerLevel[level] = []; }
    partnershipId = parent.id;
  }

  // Assume that the partnership already has a slot assigned
  const partnershipOffset = partnershipsPerLevel[level].indexOf(partnershipId);
  if(partnershipOffset === -1) {
    // Apparently not
    return partnershipsPerLevel[level].push(partnershipId) - 1;
  }
  return partnershipOffset;
}

const lineRadius = 10;
const offsetStep = 5;
const linkFn = link => {
  const thisParent = link.source;
  const partnerId = link.target.data.parents.find(p => p !== thisParent.id);
  const partners = thisParent.data.partners || [];

  // Let the first link start with this negative offset
  // But when a node has only one partner,
  // treat it the same as when it has zero
  const startOffset = (partners.length > 1)
    ? -(partners.length * offsetPerPartner) / 2
    : 0;

  const partner = partners.find(p => p.id === partnerId);

  // Chaos has no partner, nor Zeus with Athena
  const nthPartner = partner !== undefined
    ? partners.indexOf(partner)
    : (partners || []).length;
  const partnershipOffset = getPartnershipOffset(thisParent, partner);

  return drawLinkCurve(
    thisParent.y,
    thisParent.x + startOffset + offsetPerPartner * nthPartner,
    link.target.y,
    link.target.x,
    offsetStep * partnershipOffset,
    lineRadius
  );
};

function draw(root) {
  // Now every node has had it's position set, we can draw them now
  const nodes = root.descendants()
    .filter(n => !n.id.startsWith("pseudo-"));
  const links = getLinks(nodes)
    .filter(l => !l.source.id.startsWith("pseudo-"));

  const link = graphGroup.selectAll(".link")
    .data(links);
  link.exit().remove();
  link.enter()
    .append("path")
    .attr("class", "link")
    .merge(link)
    .attr("stroke", d => colours(d.target.data.parents.sort().join("-")))
    .attr("d", linkFn);

  const node = graphGroup.selectAll(".node")
    .data(nodes);
  node.exit().remove();
  const newNode = node.enter()
    .append("g")
    .attr("class", "node");

  newNode.append("path")
    .attr("d", drawNodePath);
  newNode.append("text")
    .attr("dy", -3)
    .attr("x", 6);

  newNode.merge(node)
    .attr("transform", d => `translate(${d.y},${d.x})`)
    .selectAll("text")
    .text(d => d.id);
}

const root = d3.stratify()
  .parentId(d => d.parent)
  (nodes);

// Map the different sets of parents,
// assigning each parent an array of partners
getLinks(root.descendants())
  .filter(l => l.target.data.parents)
  .forEach(l => {
    const parentNames = l.target.data.parents;
    if (parentNames.length > 1) {
      const parentNodes = parentNames.map(p => nodes.find(n => n.id === p));

      parentNodes.forEach(p => {
        if (!p.partners) {
          p.partners = [];
        }
        parentNodes
          .filter(n => n !== p && !p.partners.includes(n))
          .forEach(n => {
            p.partners.push(n);
          });
      });
    }
  });

// Take nodes with more partners first,
// also counting the partners of the children
root
  .sum(d => (d.value || 0) + (d.partners || []).length)
  .sort((a, b) => b.value - a.value);

const tree = d3.tree()
  .size([height, width])
  .separation((a, b) => {
    // More separation between nodes with many children
    const totalPartners = (a.data.partners || []).length + (b.data.partners || []).length;
    return 1 + (totalPartners / 5);
  });

draw(tree(root));
.link {
  fill: none;
  stroke-width: 2;
}

.node path {
  stroke: black;
  stroke-width: 3;
  fill: white;
}
<script src="https://d3js.org/d3.v5.js"></script>

Video upload stops prematurely on backend server, but works well on localhost

I am working on a React project where I sell courses, and when I try to upload a video file larger than 1 GB, the upload process always stops midway. However, other files smaller than that upload without any issues.

I’m not using AWS or any other services; I’m trying to store the videos directly on my backend server (Cyber Panel).
How can I fix this? I’m still learning about this topic.

here is my code in backend

 export const uploadMultiplePelatihanVideo = async (req, res) => {
//   if (!req.files || !req.files.files) {
//     return res.status(400).json({ msg: "Tidak ada file yang diunggah." });
//   }

  const files = Array.isArray(req.files.files) ? req.files.files : [req.files.files];
  const allowedExt = [".mp4", ".avi", ".mkv"]; // Format video yang diizinkan
  const maxFileSize = 10000000000; // Batas ukuran file video 10000 MB
  const uploadedVideos = [];
  const title = req.body.title || "Tanpa Judul";

  try {
    const pelatihan = await Pelatihan.findOne({
      where: { pelatihanId: req.params.pelatihanId }
    });

    if (!pelatihan) {
      return res.status(404).json({ msg: "Pelatihan tidak ditemukan." });
    }

   
    // Loop melalui setiap file video yang diunggah
    for (const file of files) {
      const fileSize = file.data.length;
      const ext = path.extname(file.name);
      const fileName = uuidv4() + ext;
      const url = `${req.protocol}://${req.get("host")}/videos/pelatihan/${fileName}`;

      // Validasi ekstensi dan ukuran file
      if (!allowedExt.includes(ext.toLowerCase())) {
        return res.status(422).json({ msg: "Silakan unggah file video saja." });
      }

      if (fileSize > maxFileSize) {
        return res.status(422).json({ msg: `Ukuran file ${file.name} terlalu besar, maksimal 1000 MB.` });
      }

      // Pindahkan file video baru ke direktori
      await file.mv(`public/videos/pelatihan/${fileName}`, async (err) => {
        if (err) {
          return res.status(500).json({ msg: "Gagal memindahkan file video." });
        }

        // Simpan informasi video ke database
        const video = await VideoPel.create({
          pelatihanId: pelatihan.pelatihanId,
          urlVideo: url,
          title, // Judul video dari body atau default
          deskripsi: req.body.deskripsi || null,  // Deskripsi dari body atau null
        });

        uploadedVideos.push({
          fileName,
          url,
          videoId: video.videoPelId,
        });
      });
    }

    // Mengirimkan response setelah semua video berhasil diunggah
    res.status(200).json({
      msg: "Video pelatihan berhasil diunggah.",
      uploadedVideos, // Mengembalikan daftar video yang berhasil diunggah
    });
  } catch (error) {
    console.error("Error uploading video:", error);
    res.status(500).json({ msg: "Terjadi kesalahan pada server." });
  }
};
  

and in the frontend

export const uploadMultiplePelatihanVideo = async (files, id, onUploadProgress) => {
  const token = sessionStorage.getItem("authToken"); // Mendapatkan token otentikasi dari sessionStorage
  

  try {
    const response = await axios.post(
      `${API_URL}/pelatihan/${id}/upload-full-video`, 
      files, 
      {
        headers: {
          Authorization: `Bearer ${token}`, // Menyertakan token otentikasi
          "Content-Type": "multipart/form-data", // Mengatur tipe konten
        },
        onUploadProgress: onUploadProgress,
        timeout: 0, // Set timeout to 0 (no timeout)
      }
    );

    // Menampilkan notifikasi sukses menggunakan SweetAlert2
    Swal.fire({
      icon: "success",
      title: "Berhasil mengupload video",
      text: "Semua video telah berhasil diupload ke pelatihan.",
    });

    return response.data; // Mengembalikan data respons dari server
  } catch (error) {
    // Menampilkan notifikasi error menggunakan SweetAlert2
    Swal.fire({
      icon: "error",
      title: "Gagal mengupload video",
      text: error.response?.data?.msg || "Terjadi kesalahan, silakan coba lagi.",
    });

    throw error; // Lempar error agar bisa ditangani di tempat lain jika diperlukan
  }
};
function editPelatihan(){
const [previewVideos, setPreviewVideos] = useState([]);
const [uploadProgress, setUploadProgress] = useState(0);


const handleMultipleVideoSubmit = async (e) => {
  e.preventDefault();
  const { videoPel, title } = formVideo;

  if (videoPel.length === 0) {
    Swal.fire({
      icon: "warning",
      title: "Video pelatihan tidak ada",
      text: "Silakan unggah video pelatihan terlebih dahulu.",
    });
    return;
  }

  try {
    const videoFormData = new FormData();
    videoPel.forEach(file => videoFormData.append('files', file));
    videoFormData.append('title', title);

    await uploadMultiplePelatihanVideo(videoFormData, pelatihanId, (progressEvent) => {
      const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
      setUploadProgress(percentCompleted);
    });

    Swal.fire({
      icon: "success",
      title: "Video pelatihan berhasil diunggah",
      text: "Semua video pelatihan telah berhasil ditambahkan ke pelatihan.",
    });
    setFormVideo({ 
      videoPel: [],
      title: "", // Reset title setelah upload
    });
    setPreviewVideos([]);
    setUploadProgress(0); // Reset progress after upload
  } catch (error) {
    Swal.fire({
      icon: "error",
      title: "Gagal mengunggah video pelatihan",
      text: "Terjadi kesalahan saat mengunggah video pelatihan.",
    });
  }
};

return (
      <form className="space-y-4 mt-4">
          {/* Upload Video Pelatihan */}
          <div>
            <label htmlFor="videoPel" className="block text-sm font-medium text-gray-300">
              Upload Video Pelatihan
            </label>
            <input
              type="file"
              id="videoPel"
              name="videoPel"
              accept="video/*"
              multiple
              onChange={handleChange}
              className="mt-1 block w-full text-sm border border-gray-700 rounded-lg cursor-pointer text-gray-400 focus:outline-none bg-gray-700 placeholder-gray-400"
            />
            <input
              type="text"
              id="title"
              name="title"
              placeholder="Masukkan judul video"
              value={formVideo.title}
              onChange={handleChange}
              className="mt-1 block w-full text-sm border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500"
            />
            {previewVideos.length > 0 && (
              <div className="mt-2">
                {previewVideos.map((videoUrl, index) => (
                  <video key={index} src={videoUrl} controls className="mt-2 w-full max-h-64 object-cover rounded-md" />
                ))}
              </div>
            )}
            <button
              onClick={handleMultipleVideoSubmit}
              className="mt-2 bg-green-500 hover:bg-green-600 text-white py-2 px-4 rounded-lg"
            >
              Unggah Video Pelatihan
            </button>
          </div>
            <div className="mt-4">
              {uploadProgress > 0 && uploadProgress < 100 && (
                <div>
                  <progress value={uploadProgress} max="100" className="w-full" />
                  <span>{uploadProgress}%</span>
                </div>
              )}
            </div>
        </form>
)


}

Stuck like this: Screenshot

upload-full-video(failed)net::ERR_CONNECTION_CLOSEDxhr
Server side logs: No files uploaded.

The server has no upload limits.

How to make element draggable/resizeable in react to achieve resizeable column in antd table?

I’m using reacts antd library to display my table contents. I want to add a feature to resize my column widths. Hence I’m wrapping the column in my as shown below. Dragging is working fine as expected but the problem is handleMouseUp method is triggered only when I click again but not called when I release the mouse . I followed the the link https://www.w3schools.com/HOWTO/howto_js_draggable.asp to achieve it but there seems to be some problem as I stated earlier which I couldn’t figure it out.

Please help me on what could be the issue with the below code

import React from 'react';
import { memo } from 'react';

const ResizeableHeaderComponent = (props: any) => {
  const onResize = (event: MouseEvent) => {
    if (event.movementX != 0) {
      event.preventDefault();
      props.onResize(event, props.index);
    }
  };

  const handleMouseUp = () => {
    window.removeEventListener('mousemove', onResize);
  };

  const handleMouseDown = () => {
    window.addEventListener('mousemove', onResize);
    window.addEventListener('mouseup', handleMouseUp);
  };
  return (
    <>
      {props.title}
      <div
        draggable={true}
        style={{
          position: 'absolute',
          bottom: 0,
          right: '-5px',
          width: '10px',
          height: '100%',
          zIndex: 5,
          cursor: 'col-resize'
        }}
        onMouseDown={handleMouseDown}
      />
    </>
  );
};

export default memo(ResizeableHeaderComponent);

Optional chain operator – using with .map | Javascript

how I should use optional chain operator with .map in React? Should I additionally add ‘?.’ to an item inside map, and ‘?.’ before ‘.map’?

{data && data?.videoCollection?.items?.map((item : any, index : number) =>
  <div className='flex flex-col items-center w-full' key={index}>
    <p className='text-3xl font-bold text-[var(--white)] text-center mt-20 px-2'>{item?.title}</p>
    <p className='text-lg text-[var(--white)] text-center mt-8 md:max-w-[50%] px-4'>{item?.description}</p>
  </div>
)}

or

{data && data?.videoCollection?.items.map((item : any, index : number) =>
  <div className='flex flex-col items-center w-full' key={index}>
    <p className='text-3xl font-bold text-[var(--white)] text-center mt-20 px-2'>{item.title}</p>
    <p className='text-lg text-[var(--white)] text-center mt-8 md:max-w-[50%] px-4'>{item.description}</p>
  </div>
)}

which way is correct?

Next js 14 a function to retreive cookies for SSR and client components

In Next.js 14 I’m trying to have one function that can get a cookie value for both client and SSR components, but it’s failing to do that in client components. How can I have it do that for any component regardless of where it’s rendered?
I’ve been making effort with this, but the client component has a problem with it:

import { RequestCookie } from 'next/dist/compiled/@edge-runtime/cookies';
import { cookies } from 'next/headers';
import Cookies from 'js-cookie';

export const getCookie = (cookie: string): string | undefined => {
  if (typeof window === 'undefined') {
    const returnedCookie: RequestCookie | undefined = cookies().get(cookie);
    return returnedCookie && returnedCookie.value;
  } else {
    const returnedCookie: string | undefined = Cookies.get(cookie);
    return returnedCookie;
  }
};

how can I edit the style of a template-clone object? / object that will be created in the future?

document.addEventListener("DOMContentLoaded", ()=>{
    let template = document.querySelector(".template");
    let button = document.querySelector(".button");
    let screen = document.querySelector(".screen");
    button.addEventListener("click", ()=>{
    let template_clone = template.content.cloneNode(true);
    template_clone.style.background = "red";
    screen.appendChild(template_clone)
})})

I need to add an object to the screen that is a template clone and edit its style

<body>
    <button class="send">send</button>
    <div class="screen">
        <template class="template">
        <div class="box1"></div>
    </template>
    </div>       
</body>

if I try to edit the template_clone.style style it results in an error

undefined is not an object (evaluating 'template_clone.style.background = "red"')

FormData sending key:[value] instead of key:value list instead of a single value to backend how can i fix it?

i have a complex form with images and attributes… when using append or set to adding the data in a vue quasar app it work fine but the problem is i receive a list of data even for single values for example:

const sendFormData = new FormData();
sendFormData.set('title', title.value || ''); 

and in the api(django view request.data) i get :

 {...'title': ['']...}

but i want it to be like:

{...'title': ''...}

i want to use formData and wondering how can i fix this ? should i parse it back-end or is there a easy way that i am missing? i search and the only solution i find is to use a simple [key: string]: unknown object that different from using formData, thank you in advance.
… just to mention i have a function in the Pinia store to handle this like below but i don’t think it is related to the problem.

  ...const formData = payload;

  try {
 
    const Response = await api.post(
     url,
      formData,
      {
        headers: { Authorization: `JWT ${accessToken}` },
      },
    );...

ui-select Multiple Dropdown Search Input Spinner Not Showing

I am working with an AngularJS project, where I upgraded the library from ui-select2 to ui-select. After the upgrade, I’m having issues with the search input spinner not showing for multiple select dropdowns, although it works fine for single select dropdowns.

Html

<ui-select multiple ng-if="list.edit" ng-model="list.EmployeeList" theme="select2" class="col-xs-12">
   <ui-select-match allow-clear="true" placeholder="Select People for Delivery">{{$item.Name}}-{{$item.EmployeeCode}}</ui-select-match>
    <ui-select-choices refresh="selectOptionsEmployeeWithoutRelievingPromise($select.search)" refresh-delay="500" repeat="item in EmployeesWithoutRelieving">
       {{item.Name}}
    </ui-select-choices>
   <div ui-select-no-choice class="no-match-message">No matches found</div>
</ui-select>

Css

/*Custom css gif loader for search input*/
.ui_select_input_spinner .ui-select-search{
    background-image: url('../../areas/commoncontrols/scripts/fileviwer/content/css/select2-spinner.gif');
    background: url('../../areas/commoncontrols/scripts/fileviwer/content/css/select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));
    background: url('../../areas/commoncontrols/scripts/fileviwer/content/css/select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);
    background: url('../../areas/commoncontrols/scripts/fileviwer/content/css/select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);
    background: url('../../areas/commoncontrols/scripts/fileviwer/content/css/select2-spinner.gif') no-repeat 100%, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0;
}
/* Hide the search icon when loading */
.ui_select_input_spinner div.search-container.select2-search::after {
    visibility: hidden; /* or display: none; */
}

Problem Description

The above CSS works fine for a single dropdown, but it doesn’t work for the multiple dropdown. I suspect the issue lies in how the class is applied, and I need to generalize it so that it works for both single and multiple select dropdowns.

JavaScript (select.js)

ctrl.refresh = function (refreshAttr) {
    if (refreshAttr !== undefined) {
        // Debounce
        if (_refreshDelayPromise) {
            $timeout.cancel(_refreshDelayPromise);
        }
        // Automatically add the 'loading' class
        $element.addClass('ui_select_input_spinner'); // Add the 'loading' class
        _refreshDelayPromise = $timeout(function () {
            if ($scope.$select.search.length >= $scope.$select.minimumInputLength) {
                var refreshPromise = $scope.$eval(refreshAttr);
                if (refreshPromise && angular.isFunction(refreshPromise.then) && !ctrl.refreshing) {
                    ctrl.refreshing = true;
                    refreshPromise.finally(function () {
                        ctrl.refreshing = false;
                        $element.removeClass('ui_select_input_spinner'); // Remove the 'loading' class when refresh completes
                    });
                } else {
                    $element.removeClass('ui_select_input_spinner'); // Remove the class if there's no promise
                }
            } else {
                $element.removeClass('ui_select_input_spinner'); // Remove the class if input length is not met
            }
        }, ctrl.refreshDelay);
    }
};

Expected Outcome

I expect the spinner to show while fetching the results in both single and multiple ui-select dropdowns. Currently, the spinner only appears for single dropdowns, but not for multiple dropdowns.

How do I call a javascript function from Google Chrome Dev console?

When I change the theme of Home Assistant (by clicking radio button at user’s profile, demo), it calls fireEvent, if I read the source correctly.

I would like to call it from the browser’s console, but if I do

fireEvent(this, "settheme", { True });

I get

VM1775:1 Uncaught ReferenceError: fireEvent is not defined
    at <anonymous>:1:1

How can I access this function? Later I will call this function from the TamperMonkey script.