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.

How to use conditional ternary operator for mulitple cases javascript?

Hi i am trying to use ternary operator for multiple cases.

below is the code snippet,

const status_color_to_icon_name = {
    white: 'info',
    orange: 'major',
}

const default_icon_name = 'icon1';

<Icon name={status_color_to_icon_name[item.color] ?? default_icon_name} color= 
    {item.color} />

the above works fine. it looks for item name based on item.color if no name found in status_color_to_icon_name based on item.color it returns default_icon_name

now i have other condition if item.color is ‘red’ then i want to use custom_icon

i have tried below,

const custom_icon ='icon2';


const status_color_to_icon_name = {
    white: 'info',
    orange: 'major',
}

const default_icon_name = 'icon1';

<Icon name={item.color === 'red' ? custom_icon_name : 
    status_color_to_icon_name[item.color] ?? default_icon_name} color= 
    {item.color} />

but the above doesnt seem correct. could someone help me with this. thanks.

Why doesn’t Playwright reporter wait for async functions to complete?

I am using custom playwright reporter (but I think this issue is not only tied to reporter) and there in async OnTestEnd(test, result) I am trying to run exec command. With debugger turned on I see that as soon as program reaches this exec function it skips it and it ends.

async onTestEnd(test, result){
    const cmd = "some complex command"
    return new Promise((resolve, reject) => {
      exec(cmd, { timeout: 10000 }, (error, stdout, stderr) => {  // 10-seconds timeout
        if (error) {`enter code here`
          reject(error);
          return;
        }
        
        if (stderr) {
          reject(stderr);
          return;
        }
        resolve(stdout);
      });
    });
}

Above is one of many attempts to correctly run this function. But it skips all the time.

Access dynamic variable created in js (backstage.io) from a React component level file [closed]

Team A is using backstage.io an inside ../services/app/packages/backend/src/modules/auth.js they are creating microsoft token, modify this token adding some values and issuing as backstage (they are not able to provide me publick key to validate signature, don’t ask.), hence i need to catch and pass variable with microsoft token (before they modify this, yes i can change auth.js file) to my React component so during fetch (which is going through backstage proxy plugin) i could pass my microsoft token catched from auth.js as Authorization.
I have tried process.env , module.export etc. all of them are giving me undefined value from React component level and that is understandable because React env values are build on start of app.

Is there any possibility i could do this or only using token issued by them is possible

Error: runtimeTemplate.supportsAsyncFunction is not a function

I have a host and remote application developed with Angular 15.

Below is the webpack config of host:

const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const path = require('path');

module.exports = {
  entry: './src/main',
  output: {
    publicPath: 'http://localhost:4200/',
    scriptType: 'text/javascript',
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  },
  resolve: {
    extensions: ['.ts', '.js'],
  },
  module: {
  },
  optimization: {
    runtimeChunk: false,
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'host',
      remotes: {
        helloworld: 'helloworld@http://localhost:3000/remoteEntry.js',
      },
    }),
  ],
};

Below is webpack config of MFE:

const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const path = require('path');

module.exports = {
  output: {
    publicPath: 'http://localhost:3000/',
    scriptType: 'text/javascript',
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  },
  resolve: {
    extensions: ['.ts', '.js'],
  },
  module: {
    rules: [
      {
        test: /.js$/,
        type: 'babel-loader',
        exclude: /node_modules/,
      },
      {
        test: /.ts$/,
        loader: 'ts-loader',
        options: {
          configFile: 'tsconfig.app.json',
        },
      },
    ],
  },
  optimization: {
    runtimeChunk: false,
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'helloworld',
      exposes: {
        './HelloWorldModule': './src/app/hello.module.ts',
      },
    }),
  ],
};

I am loading the MFE module in host using following code:

  {
    path: 'flights-search',
    loadChildren: () => // @ts-ignore
    // eslint-disable-next-line no-console
    import('helloworld/HelloWorldModule').then(m => m.Module).catch(error => console.log('Error=>', error))
  },

On running npm start in host, I get following error:
external “helloworld@http://localhost:3000/remoteEntry.js” – Error: runtimeTemplate.supportsAsyncFunction is not a function

Below are the packages I am using:

“webpack-bundle-analyzer”: “4.5.0”,
“webpack-cli”: “4.9.2”,
“webpack”: “^5.94.0”,
“webpack-dev-server”: “^4.11.1”,
“@angular-builders/custom-webpack”: “^15.0.0”

My mapplic v7 code cannot open on iPad or iPhone [closed]

This is using mapplic.js version 7. I think the problem is in the code below. I hope my map can be opened on an iPhone or iPad

self.addMarker = function(location) {
  // hidden marker
  if (location.pin.indexOf('hidden') != -1) 
    return false;
    
  var parent = $('.mapplic-layer[data-floor=' + location.level + '] .mapplic-map-image', self.el);
  var marker = $('<a></a>').addClass('mapplic-pin').addClass(location.pin.replace('hidden', '')).attr('aria-label', location.title + ' marker').css({
    'top': (location.y * 100) + '%',
    'left': (location.x * 100) + '%'
  }).appendTo(parent);
  
  marker.on('click touchend', function(e) {
    if (e.cancelable) e.preventDefault();
    if (!self.dragging) self.showLocation(location.id, 600);
  });
  
  if (location.label) {
    if (location.label.match(/(http(s)?://.)?(www.)?[-a-zA-Z0-9@:%._+~#=]{2,256}.[a-z]{2,6}b([-a-zA-Z0-9@:%_+.~#?&//=]*)/g)) marker.css('background-image', 'url(' + location.label + ')');
    else $('<span><span>' + location.label + '</span></span>').appendTo(marker);
  }
  
  if (location.reveal) 
    marker.attr('data-reveal', location.reveal).css('visibility', 'hidden');
    
  if (location.category) {
    location.category = location.category.toString();
    marker.attr('data-category', location.category);
  }
  
  marker.attr('data-location', location.id);
  
  if (self.o.zoom && self.o.mousewheel) 
    marker.on('mousewheel DOMMouseScroll', self.mouseWheel);
    
  if (location.styled)
    marker.addClass(location.styled);
    
  if (location.color && location.pin.indexOf('pin-text') > -1) 
    marker.css('color', location.color);
  else if (location.color) 
    marker.css({
      'background-color': location.color,
      'border-color': location.color
    });
    
  location.el = marker;
  return marker;
}

I get the following error when i try to execute the command npm run build on my game project in visual studio code:

I am following a course to create a TS/JS-based game through webpack and Phaser. My GameScene Code is

import { Map } from "../components/map";

import TilesGroup from "../components/tiles/tilesGroup";
import Player from "../components/player/player";

export default class MainScene extends Phaser.Scene{
  player: Player
  tileGroup: TilesGroup
  cursors: Phaser.Input.Keyboard.CursorKeys
  level: number
  constructor(){
    super({
      key: "MainScene"
    })
    
  }
  init(props: {level? : number}){
    const {level = 0} = props
    this.level= Map.calcCurrentLevel(level)

  }

  create(){
    const map= new Map(this.level)
    this.cameras.main.setBackgroundColor('#ade6ff')
    this.cameras.main.fadeIn()

    this.cameras.main.setBounds(map.size.x, map.size.y, map.size.width, map.size.height)
    this.physics.world.setBounds(map.size.x, map.size.y, map.size.width, map.size.height)
    this.input.addPointer(1)
    this.cursors = this.input.keyboard.createCursorKeys()


    this.tileGroup= new TilesGroup(this,map.info.filter((el: TilesConfig) => el.type==="tile"))
    this.player= new Player(this,map.info.filter((el: TilesConfig) => el.type==="player")[0], map.size, this.level) 
  
    this.cameras.main.startFollow(this.player)
    this.physics.add.collider (this.tileGroup, this.player)
  }

update(time: number, delta: number): void{
  this.player.update(this.cursors)
}

}

I get the following webpack error when i try to run the command npm run build:



[webpack-cli] Failed to load 'C:UsersvivekLearningdemoplatformer+gameplatformer gamewebpackwebpack.dev.js' config
[webpack-cli] Invalid options object. Copy Plugin has been initialized using an options object that does not match the API schema.  
 - options[0] has an unknown property 'to'. These properties are valid:
   object { patterns, options? }
 - options[1] has an unknown property 'to'. These properties are valid:
   object { patterns, options? }
 - options[2] has an unknown property 'to'. These properties are valid:
   object { patterns, options? }

I was expecting the webpack to be ready and run my game through the command npm start