InteractJS Drag-and-Drop: Cards Not Dropping in Correct Position

I’m using InteractJS’s draggable and dropzone functions to implement a drag-and-drop UI, but my cards are not landing in the correct position within the drop zones. The endPosition is misaligned, sometimes defaulting to 0 or resolving incorrectly (e.g., 5 instead of 2). I’ve confirmed that contentZones contains the correct drop areas, but dropzone isn’t always matching them properly. How can I ensure that dropped elements correctly align with their expected positions?

Here is the use of InteractJS’s dropzone and draggable:

interact('.content').dropzone({
    accept: '.card',
    overlap: 0.5,
    ondrop: function(event){
        const dragged = event.relatedTarget;
        const dropzone = event.target;
        
        const contentZones = Array.from(document.querySelectorAll('.content'));
        const startPosition = dragged.originalContentIndex ?? contentZones.indexOf(dragged.closest('.draggable-content'));
        const endPosition = contentZones.indexOf(dropzone);
        
        // Validate positions
        if (endPosition === -1 || startPosition === endPosition) {
            console.log('Invalid move detected:', { startPosition, endPosition });
            return;
        }

        // Handle existing card first
        const existing = dropzone.querySelector('.card');
        if (existing && existing !== dragged) {
            // Remove existing card before any other DOM changes
            dropzone.removeChild(existing);
            
            // Calculate next position
            let nextIndex = endPosition + 1;
            if (nextIndex >= contentZones.length) {
                nextIndex = 0;
            }
            
            //const targetZone = contentZones[nextIndex];
            const targetZone = contentZones[endPosition];
if (!targetZone) {
    console.error(` drop zone not found at index ${endPosition}`);
    return;
}

console.log(`Target drop zone confirmed:`, targetZone.id || 'No ID');

            
            // Move existing card
            /*targetZone.appendChild(existing);
            resetElementStyle(existing);*/
            
            // Update backend for existing card
            const existingGroupID = existing.querySelector('.dropdown-item[data-group-id]')?.getAttribute('data-group-id');
            const existingItemID = existing.querySelector('.dropdown-item[data-group-id]')?.getAttribute('data-item-id');
            const existingAppTreeID = existing.querySelector('.dropdown-item[data-applicationtreeid]')?.getAttribute('data-applicationtreeid');
            
            if (existingGroupID && existingItemID && existingAppTreeID) {
                /*moveItemMultipleLevels(
                    existingAppTreeID,
                    existingGroupID,
                    existingItemID,
                    'down',
                    1,
                    endPosition,
                    nextIndex,
                    dropzone
                );*/
            }
        }

        // Handle dragged card
        if (dragged.parentNode) {
            //dragged.parentNode.removeChild(dragged);
        }
        
        /*dropzone.appendChild(dragged);
        resetElementStyle(dragged);*/
        
        // Update backend for dragged card
        const direction = endPosition > startPosition ? 'down' : 'up';
        const levels = Math.abs(endPosition - startPosition);
        
        const dropdownItem = dragged.querySelector('.dropdown-item[data-group-id]');
        if (dropdownItem) {
            const groupID = dropdownItem.getAttribute('data-group-id');
            const itemID = dropdownItem.getAttribute('data-item-id');
            const applicationTreeID = dropdownItem.getAttribute('data-applicationtreeid');
            
            console.log('Available move actions:', Array.from(dragged.querySelectorAll('.dropdown-item')).map(action => ({
                href: action.getAttribute('href'),
                groupID: action.getAttribute('data-group-id'),
                itemID: action.getAttribute('data-item-id'),
                applicationTreeID: action.getAttribute('data-applicationtreeid')
            })));

            if (groupID && itemID && applicationTreeID && levels > 0) {
              //alert(startPosition);
              //alert(endPosition);
                moveItemMultipleLevels(
                    applicationTreeID,
                    groupID,
                    itemID,
                    direction,
                    levels,
                    startPosition,
                    endPosition,
                    dropzone
                );
            }
        }
        
        // Update tracking
        //dragged.originalContentIndex = endPosition;
    }
});

interact('.card').draggable({
    inertia: false,
    autoScroll: true,
    listeners: {
        start(event) {
          //alert('start');
            const target = event.target;
            const rect = target.getBoundingClientRect();
            
            dragStartPosition.x = event.clientX;
            dragStartPosition.y = event.clientY;
            console.log('drag start event.clientY: ' + event.clientY);
            
            dragOffset.x = event.clientX - rect.left;
            dragOffset.y = event.clientY - rect.top;

            const computedStyle = window.getComputedStyle(target);
            
            target.originalStyles = {
                width: computedStyle.width,
                height: computedStyle.height,
                minWidth: computedStyle.minWidth,
                minHeight: computedStyle.minHeight,
                maxWidth: computedStyle.maxWidth,
                maxHeight: computedStyle.maxHeight,
                position: computedStyle.position,
                flex: computedStyle.flex,
                flexBasis: computedStyle.flexBasis,
                flexGrow: computedStyle.flexGrow,
                flexShrink: computedStyle.flexShrink
            };

            const deltaX = event.clientX - dragStartPosition.x;
            const deltaY = event.clientY - dragStartPosition.y;
            direction = Math.abs(deltaX) > Math.abs(deltaY)
        ? (deltaX > 0 ? 'down' : 'up')
        : (deltaY > 0 ? 'down' : 'up');

            const contentZones = Array.from(document.querySelectorAll('.content'));
            target.originalContentIndex = contentZones.indexOf(target.closest('.content'));
            startPosition = contentZones.indexOf(target.closest('.content'));

            target.style.width = computedStyle.width;
            target.style.height = computedStyle.height;
            target.style.minWidth = computedStyle.width;
            target.style.minHeight = computedStyle.height;
            target.style.maxWidth = computedStyle.width;
            target.style.maxHeight = computedStyle.height;
            target.style.flex = 'none';
            target.style.position = 'fixed';
            target.style.zIndex = 1000;
            target.style.left = (event.clientX - dragOffset.x) + 'px';
            target.style.top = (event.clientY - dragOffset.y) + 'px';
            target.classList.add('dragging');
        },

        move(event) {
            const target = event.target;
            target.style.left = (event.clientX - dragOffset.x) + 'px';
            target.style.top = (event.clientY - dragOffset.y) + 'px';
            dragLastPosition.x = event.clientX;
            dragLastPosition.y = event.clientY;
            
            // Track zones moved over for cards
            const elementsUnder = document.elementsFromPoint(event.clientX, event.clientY);
            //console.log('Elements detected at drop point:', elementsUnder.map(el => el.className));
            const containerUnder = elementsUnder.find(el => el.classList.contains('content'));
            /*if (containerUnder) {
                zonesMovedOver.add(containerUnder);
            }*/
            const correctedLevelsMoved = Math.min(zonesMovedOver.size - 1, 2); // Prevent excessive zone shifts
            const endPosition = startPosition + (direction === 'up' ? -1 : 1) * correctedLevelsMoved;

            if (containerUnder && !zonesMovedOver.has(containerUnder)) {
              //alert('added!');
              zonesMovedOver.add(containerUnder);
              console.log('Added container:', containerUnder.id);
            }
            
        },

        end(event) {
            const target = event.target;

            // Reset styles
            target.classList.remove('dragging');
            Object.entries(target.originalStyles).forEach(([key, value]) => {
                target.style[key] = value;
            });
            target.style.position = 'relative';
            target.style.left = '0';
            target.style.top = '0';

            const contentZones = Array.from(document.querySelectorAll('.content'));
            const startPosition = target.originalContentIndex ?? contentZones.indexOf(target.closest('.content'));
            const endPosition = target._dropIndex;

            // Only proceed if we have a valid drop
            if (endPosition === undefined || startPosition === endPosition) return;

            const direction = endPosition > startPosition ? 'down' : 'up';
            const levels = Math.abs(endPosition - startPosition);
            alert('this moveItemMultipleLevels, direction: ' + direction);

            const dropzone = contentZones[endPosition];
            const existing = dropzone.querySelector('.card');

            // Move existing card first if needed
            if (existing && existing !== target) {
                let nextIndex = endPosition + 1;
                if (nextIndex >= contentZones.length) nextIndex = 0;

                const targetZone = contentZones[1];
                //const targetZone = layoutGroup3.querySelector(`.content:nth-child(${expectedIndex + 1})`);


                if (!existing.contains(targetZone)) {
                    targetZone.appendChild(existing);
                    resetElementStyle(existing);

                    const existingGroupID = existing.querySelector('.dropdown-item[data-group-id]')?.getAttribute('data-group-id');
                    const existingItemID = existing.querySelector('.dropdown-item[data-group-id]')?.getAttribute('data-item-id');
                    const existingAppTreeID = existing.querySelector('.dropdown-item[data-applicationtreeid]')?.getAttribute('data-applicationtreeid');

                    if (existingGroupID && existingItemID && existingAppTreeID) {
                        moveItemMultipleLevels(
                            existingAppTreeID,
                            existingGroupID,
                            existingItemID,
                            'down',
                            1,
                            endPosition,
                            nextIndex
                        );
                    }
                } else {
                    console.warn('Blocked circular move: existing card contains targetZone.');
                    return;
                }
            }

            // Now drop the dragged card
            dropzone.appendChild(target);
            resetElementStyle(target);

            // Backend update for dragged card
            const draggedContainerMenu = target.closest('.card');
            if (draggedContainerMenu) {
                const dropdownItem = draggedContainerMenu.querySelector('.dropdown-item[data-group-id]');
                if (dropdownItem) {
                    const groupID = dropdownItem.getAttribute('data-group-id');
                    const itemID = dropdownItem.getAttribute('data-item-id');
                    const applicationTreeID = dropdownItem.getAttribute('data-applicationtreeid');

                    if (groupID && itemID && applicationTreeID && levels > 0) {
                        moveItemMultipleLevels(
                            applicationTreeID,
                            groupID,
                            itemID,
                            direction,
                            levels,
                            startPosition,
                            endPosition
                        );
                    }
                }
            }

            // Update index for future moves
            target.originalContentIndex = endPosition;
            delete target._dropIndex; // Clean up
        }
    }
});

Here is moveItemMultipleLevels:

const moveItemMultipleLevels = async (applicationTreeID, groupID, itemID, direction, levels, startPosition, endPosition, dropzone) => {
  console.log('moveItemMultipleLevels called with:', {
    applicationTreeID,
    groupID,
    itemID,
    direction,
    levels,
    startPosition,
    endPosition,
    dropzone,
    moving: `from position ${startPosition} to position ${endPosition}`
  });
  const moves = [];
  try {
    const fetchUrl = `index.cfm?fa=MoveGroupItem&ApplicationTreeID=${applicationTreeID}&GroupID=${groupID}&ItemID=${itemID}&direction=${direction}&levels=${levels}`;
    const response = await fetch(fetchUrl);
    if(!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    moves.push(data);
    await new Promise(resolve => setTimeout(resolve, 100));
    // Ensure dragged card is properly detected
    const draggedCard = window.draggedCard;
    if(!draggedCard) {
      console.error(`No dragged card detected—dragging not properly initiated.`);
      return;
    }
    console.log('Dragged card detected:', draggedCard.querySelector('.dropdown-item')?.dataset.itemId);
    const layoutGroup3 = document.querySelector('#Content_2BEC2B57-5E08-4F32-9DDC6006A8B13775');
    if(!layoutGroup3) {
      console.error('Layout Group 3 not found');
      return;
    }
    // Get all content zones inside Layout Group 3
    const contentZones = Array.from(layoutGroup3.querySelectorAll('.content'));
    console.log('Debugging Layout Group 3 structure before drop:');
    console.log('Detected zones:', contentZones.map((zone, i) => `Index ${i}: ${zone.id || 'No ID'}`));
    console.log('Detected cards:', contentZones.map((zone, i) => `Index ${i}: ${zone.querySelector('.card')?.id || 'Empty'}`));
    console.log('Expected drop at index:', endPosition);
    document.querySelectorAll('.card').forEach((card, index) => {
      card.setAttribute('id', `card-${index}`);
      window.draggedCard = card;
      console.log(`Assigned ID to card: card-${index}`);
    });
    console.log('Detected draggable cards:', [...document.querySelectorAll('.card')].map(card => card.id));
    contentZones.forEach(zone => {
      zone.addEventListener('drop', (event) => {
        event.preventDefault();
        console.log(`Attempting drop...`);
        console.log(`window.draggedCard at drop:`, window.draggedCard);
        if(!window.draggedCard) {
          console.error('No dragged card detected.');
          return;
        }
        zone.appendChild(window.draggedCard);
        console.log(`Dropped card successfully.`);
      });
    });
    // Ensure the drop is happening within valid content zones
    if(endPosition < 0 || endPosition >= contentZones.length) {
      console.error(`Invalid drop index: ${endPosition}.`);
      return;
    }
    //const targetZone = contentZones[endPosition];
    const expectedIndex = contentZones.findIndex(zone => zone === dropzone);
    if(expectedIndex === -1) {
      console.error(`Dropzone not found in contentZones.`);
      return;
    }
    endPosition = expectedIndex;
    console.log('Calculated drop position:', endPosition);
    const targetZone = layoutGroup3.querySelector(`.content:nth-child(${expectedIndex + 1})`);
    if(!targetZone) {
      console.error(`Target drop zone not found at index ${endPosition}`);
      return;
    }
    console.log(`Target drop zone confirmed:`, targetZone.id || 'No ID');
    // Move the dragged card to the new position
    console.log('targetZone');
    console.log(targetZone);
    console.log('draggedCard');
    console.log(draggedCard);
    console.log('endPosition');
    console.log(endPosition);
    if(draggedCard.parentNode) {
      draggedCard.parentNode.removeChild(draggedCard);
    }
    targetZone.appendChild(draggedCard);
    console.log(`Dragged card moved to position ${endPosition}`);
    // Cleanup hover effect
    contentZones.forEach(zone => zone.classList.remove('hovered'));
    return moves;
  } catch (error) {
    console.error('Error in moveItemMultipleLevels:', error);
    throw error;
  }
};

I tried debugging by logging detected zones and verifying dropzone against contentZones, but dropzone isn’t always found in the expected location, and the cards occasionally land in unintended areas. I’m looking for guidance on ensuring accurate positioning within drop zones.

Azure Communication Service add participants not working

I was trying to add a phone number to a call using Azure Communication Service but it kept failing

const incoming_context = event.data.incomingCallContext;
                    const answer_res = await client.answerCall(incoming_context, `${config.domain}`);

                    await answer_res.callConnection.addParticipant([{
                        targetParticipant: { phoneNumber: '+xxxxxxxxxxx' },
                        sourceDisplayName: "Info",
                        sourceCallerIdNumber: { phoneNumber: '+xxxxxxxxxxx' }
                    }]);
Received 1 event(s)
Error answering call: TypeError: Cannot read properties of undefined (reading 'communicationUserId')
at isCommunicationUserIdentifier (C:UsersrohitDesktopgitcall-recordnode_modules@azurecommunication-commondistindex.js:326:30)
at getIdentifierKind (C:UsersrohitDesktopgitcall-recordnode_modules@azurecommunication-commondistindex.js:366:9)
at serializeCommunicationIdentifier (C:UsersrohitDesktopgitcall-recordnode_modules@azurecommunication-commondistindex.js:518:28)
at communicationIdentifierModelConverter (C:UsersrohitDesktopgitcall-recordnode_modules@azurecommunication-call-automationdistcommonjsutliconverters.js:95:94)
at CallConnection.addParticipant (C:UsersrohitDesktopgitcall-recordnode_modules@azurecommunication-call-automationdistcommonjscallConnection.js:130:89)
at C:UsersrohitDesktopgitcall-recordapp.js:34:53
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)

Is there a way to select and deselect an entire group of choices on a pickerInput from shinyWidgets in 2025?

I am aware there is a similar question that was answered pre 2023, but the internal structure of pickerInput has changed since. – Old Fix

I will also use the same reproducible example used in that question:

library(shiny)
library(shinyWidgets)

ui <- fluidPage(
    pickerInput("test",choices=list("A"=c(1,2,3,4,5),"B"=c(6,7,8,9,10)),multiple=TRUE),
    textOutput("testOutput")
)

server <- function(input, output) {
    output$testOutput <- renderText({paste(input$test)})
}

shinyApp(ui = ui, server = server)

The goal is to click A and have the pickerInput automatically select 1,2,3,4 and 5 or/and if we click B, it automatically selects 6,7,8,9, and 10.

I also want the reverse, so clicking A and B when they are selected deselects 1,2,3,4 and 5 and 6,7,8,9, and 10 respectively.

Desired ouput after clicking “A”

SVG will translate but won’t rotate

This rect translates fine but won’t rotate but I can’t see the typo or syntax error.
[Firefox 138.0(64bit) on openSUSE Tumbleweed]

    <script  id="svgScript" type="text/javascript">
        //https://github.com/amitonline/true-ruler/blob/main/js/true-ruler.js
        var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
        svg.setAttribute("id","sliderControl");
        svg.setAttribute("viewBox","0 0 100% 100%");
        svg.setAttribute("width","100%");
        svg.setAttribute("height","200px");
        
        var svgNS = svg.namespaceURI;


        const periodPill = document.createElementNS(svgNS, "rect");
        periodPill.setAttribute("x", "0");
        periodPill.setAttribute("y", "0");
        periodPill.setAttribute("width", "30");
        periodPill.setAttribute("height", "30");
        periodPill.setAttribute("transform-origin", "center");
        periodPill.setAttribute("transform", "rotate(45)");
        periodPill.setAttribute("transform", "translate(532,85)");
        periodPill.setAttribute("fill", "#55aaff");
        periodPill.setAttribute("opacity","100%");
        periodPill.setAttribute("cursor", "move");
        svg.appendChild(periodPill);

        document.body.appendChild(svg);
    </script>

Inject/execute JavaScript from Python script

I’m executing a method in my Python script that triggers a function in my HTML file:

def OnLoadingStateChange(self, browser, is_loading, **_):
    if not is_loading:
        self.container.page_loaded = True

        blueprint_text = """
            Begin Object Class=/Script/BlueprintGraph.K2Node_Event Name="K2Node_Event_1" ExportPath="/Script/BlueprintGraph.K2Node_Event'/Game/ANCIENT_DRAGON/ABP_AncientDragon.ABP_AncientDragon:EventGraph.K2Node_Event_1'"
            NodePosX=3392
            NodePosY=-64
            NodeGuid=EC7283AA406DE84613834BA97BBD68F1
            EventReference=(MemberParent="/Script/CoreUObject.Class'/Script/Engine.AnimInstance'",MemberName="AnimNotify_FootShake")
            CustomFunctionName="AnimNotify_FootShake"
            CustomProperties Pin (PinId=318791834E3D459539EC3B87A24112FB,PinName="OutputDelegate",Direction="EGPD_Output",PinType.PinCategory="delegate",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(MemberParent="/Script/Engine.AnimBlueprintGeneratedClass'/Game/ANCIENT_DRAGON/ABP_AncientDragon.ABP_AncientDragon_C'",MemberName="AnimNotify_FootShake",MemberGuid=EC7283AA406DE84613834BA97BBD68F1),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False)
            End Object
        """

        js_code = f'renderBlueprint("{blueprint_text}");'
        browser.ExecuteJavascript(js_code)

When I exclude the below line, it works fine but when included it gives an error stating that the node cannot be rendered.

CustomProperties Pin (PinId=318791834E3D459539EC3B87A24112FB,PinName="OutputDelegate",Direction="EGPD_Output",PinType.PinCategory="delegate",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(MemberParent="/Script/Engine.AnimBlueprintGeneratedClass'/Game/ANCIENT_DRAGON/ABP_AncientDragon.ABP_AncientDragon_C'",MemberName="AnimNotify_FootShake",MemberGuid=EC7283AA406DE84613834BA97BBD68F1),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False)

I’ve tried including this within the function to help the formatting but it makes no difference:

escaped_text = (
    blueprint_text
    .replace('\', '\\')
    .replace('n', '\n')
    .replace('"', '\"')
)

This is the function in my HTML file:

function renderBlueprint(blueprintText) {
// Stop any existing renderer
if (renderer) {
    renderer.stop();
    playground.innerHTML = ''; // Clear the playground
}
// Create and start a new renderer
renderer = new window.blueprintUE.render.Main(
    blueprintText,
    playground,
    { height: "100vh" }
);
renderer.start();

I’ve uploaded the JS file here.

Can anyone see why the “CustomProperties Pin” line would break its functionality?

Using a css and js autocomplete api or something in a VSCode extension

I created a new code language that accepts css and js codes. Just like html supports css and js, my new language also supports css and js codes. Everything is working fine, but the problem is that I can’t make the css and js codes auto-extract and colored, so I’m trying to do it manually, which can lead to more errors. Is there a special service that can help me do this? I found the following service, but it only works in the browser. I need it to be used in an extension. I would appreciate any help.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>CSS Auto Completion with Monaco Editor</title>
  <style>
    #editor {
      width: 100%;
      height: 400px;
      border: 1px solid #ccc;
    }
  </style>
</head>
<body>

<div id="editor"></div>

<script src="https://unpkg.com/monaco-editor@latest/min/vs/loader.js"></script>
<script>
  require.config({ paths: { 'vs': 'https://unpkg.com/monaco-editor@latest/min/vs' } });

  require(['vs/editor/editor.main'], function () {
    monaco.editor.create(document.getElementById('editor'), {
      value: ``,
      language: "css",
      theme: "vs-dark",
      fontSize: 14,
      automaticLayout: true
    });
  });
</script>

</body>
</html>

I tried several options like the example above, but none of them seem to work within the extension.

File Picker and Upload Functionality Not Working in Moodle LMS

I created a course and tried to add a SCORM file using the File Picker. However, when I click the ‘Add’ button, nothing happens—the popup window for file upload does not appear. I also attempted to upload PNG and JPG files instead of the SCORM package, but the issue persists. The file upload functionality is not working on the Moodle LMS site.

I can see error in DOM (screen attached).
enter image description here

Spring Boot font files return 404 or 302 only when browser DevTools are open (localhost)

I’m working on a Spring Boot application with the following setup:

Spring Boot version: 2.4.1

Java version: 1.8

Using spring-boot-starter-security and spring-boot-starter-web

Application context path is set to /admin via application.yml: server:   servlet:     context-path: /admin Font files are located in: src/main/resources/static/FKGroteskNeue-1.1.1/woff-static/ and woff2-static/

CSS references fonts using absolute paths like:

@font-face {   font-family: "FK Grotesk Neue";   src: url('/admin/FKGroteskNeue-1.1.1/woff2-static/FKGroteskNeue-Regular.woff2') format('woff2'),        url('/admin/FKGroteskNeue-1.1.1/woff-static/FKGroteskNeue-Regular.woff') format('woff'); }

When I access the app via http://localhost:8085/admin/…, everything works until I open browser DevTools.

As soon as I open DevTools (Inspect Element), font requests like:

http://localhost:8085/FKGroteskNeue-1.1.1/woff2-static/FKGroteskNeue-Regular.woff2
return either:

404 Not Found, or
302 Found → redirecting to /admin/login
When I access the app using my local IP address (e.g., http://192.168.x.x:8085), the fonts load fine — even with DevTools open.

I Verified font files exist in target/classes/static/…
Updated pom.xml to exclude font files from filtering
Cleared browser cache and tried Incognito mode.
Updated Spring Security config to permit font paths:
.antMatchers(“/admin/FKGroteskNeue-1.1.1/**”).permitAll()

When switching between “films” and “serials”, previous content is not replaced and incorrect cards are shown

Problem, need to clean up the network

•   When I open the /films page, a request is made to films.json and movie cards are displayed.
•   As I scroll down, more films are loaded in batches of 20 — works fine so far.
•   Then I navigate to /serials, a request to serials.json is made and serial cards are shown — also works fine.
•   But when I go back to /films, a new request is correctly made to films.json, but the serial cards from the previous view are still on the page, instead of being replaced with films.

So the path changes and the new request is triggered, but the old cards (from /serials) remain.

Expected behavior: When switching routes, the current cards should be cleared, and only the new content relevant to the route should be shown.

What I’ve tried:

  • Clearing sessionstorage

Any ideas on what might be going wrong?

export default function MoviesList({
                                       mainpage,
                                       referer,
                                       list = [],
                                       filterData,
                                       catalogData,
                                       searchParams,
                                       priorityArray,
                                       query = undefined,
                                       setNewData = null,
                                       sessionStorageFilms,
                                       sessionStorageSerials,
                                       maximumAgeLevel,
                                       isHistoryCard
                                   }) {
    const [data, setData] = useState(list);
    const [reset, setReset] = useState(false);
    const [asPath, setAsPath] = useState(searchParams?.categoryAlias);
    const skipNumber =
        asPath === «films»
            ? sessionStorageFilms?.length
            : asPath === «serials»
                ? sessionStorageSerials?.length
                : +process.env.LIMIT_SCROLL_ITEMS_PER_PAGE;

    if (asPath !== searchParams?.categoryAlias) {
        // when the page changes, a command to reset skip is sent
        setAsPath(searchParams.categoryAlias);
    }

    const { result, loading } = infiniteScrollMovieList(
        mainpage,
        catalogData,
        searchParams,
        filterData,
        reset,
        query,
        skipNumber, //to load the number of subsequent films stored in sessionStorage
        maximumAgeLevel,
        sessionStorageFilms,
        sessionStorageSerials
    );

    useEffect(() => {
        if (
            result?.items?.length &&
            data?.length &&
            result.items[result?.items?.length - 1].name !== data[data.length - 1].name
        ) {
            const newData = [...data, ...result?.items];

            if (
                setNewData === null &&
                sessionStorageSerials?.[20]?.name !== result?.items[0].name &&
                sessionStorageFilms?.[20]?.name !== result?.items[0].name
            ) {
                setData(newData);

                if (asPath === «films») {
                    sessionStorage.setItem(«films», JSON.stringify(newData));
                } else if (asPath === «serials») {
                    sessionStorage.setItem(«serials», JSON.stringify(newData));
                }
            } else if (
                setNewData !== null &&
                !Boolean(
                    data.find(item => item.name === result.items[result?.items?.length - 1].name)
                )
            ) {
                setNewData(newData);
            }
        }
    }, [result, sessionStorageSerials, sessionStorageFilms]);

    useEffect(() => {
        // retrieve films from sessionStorage, if they are there
        if (asPath === «films») {
            list.length > 0 && setData(sessionStorageFilms?.length > 0 ? sessionStorageFilms : list);
        } else if (asPath === «serials») {
            list.length > 0 && setData(sessionStorageSerials?.length > 0 ? sessionStorageSerials : list);
        } else {
            setData(list);
        }

        if (setNewData === null) {
            setReset(true);
            setTimeout(() => {
                setReset(false);
            }, 1000);
        }
    }, [asPath, filterData, list, sessionStorageSerials, sessionStorageFilms, setNewData]);

thanks

with a function to map a point onto a quadrilateral, can you make a quadrilateral in which 3 points maintain their relative position inside it? [closed]

I program in JavaScript, and a recent problem I’ve been facing is related to a feature I implemented that interpolates a point between a quadrilateral like so

This is a rough depiction of point interpolation

It works perfectly fine, however another feature I need to make is the ability to get the opposite.

Is it possible to create an algorithm that can take an input of 3 points between 0 and 1 and output the corner coordinates of a quadrilateral that matches? Here’s a diagram to help explain it if it helps. The points on the quadrilateral match the points in the corner

If so, a guide on how to implement it would be great.

I’ve been basically brute-forcing this idea for a while to no avail. I just might simply be not smart enough to tackle the problem, I can get one point into place but not two or three at the same time.

Formatting output of the Web Speech API

record = new SpeechRecognition();
record.onresult = (speech) => { alert(speech.results[0][0].transcript); }
record.start();

First letter of above code`s output is upper case. How can it come from server as lower case?

For example, output text is: Here we go.

However, demanded text is: here we go.

toLowerCase method is not accepted in this thread.

In my react app, browser refresh/reload redirects me to home page

I am using Reactjs for building the app. My Route page, index.js and App page looks like below. When I open the app, it lands in a home page, I select 1 of the radio buttons, submit it. It navigates to the next page. Now if I click on browser refresh/reload button, it redirects me to home page instead of reloading same page which is the default behaviour.

Routes Page

`const Routes = () => {
  const element = (
    <ReactRoutes>
      <Route path="/" element={<MainView />} />
      <Route path="/Home" element={<Home />} />
      <Route exact path='/login' element={<Login />} />
      <Route path="/Management" element={<ManagementTable />} />
      <Route path="/Overview" element={<Overview />} />
    </ReactRoutes>
  );
  return element;
};
export default Routes;`

App.jsx

    const App = () => {
  const [isAuthState,setIsAuthState] = useState(false);
  const { authState } = useOktaAuth();
  useEffect(() => {
    if(authState && authState !== null) {
      setIsAuthState(true);
    }
  }, [authState]);

  if (isAuthState && authState?.isAuthenticated) {
    return (
      <>
          <Header />
          <MainNav />
          <Routes />
          <GlobalFooter />
      </>
    );
  } else {
    return (
      <CustomRoutes>
        <Route exact path='/login' element={<Login />} />
        <Route exact path='/login/callback' element={<LoginCallback />} />
        <Route path='*' element={<Login />} />
      </CustomRoutes>
    );
  }
};
export default OktaWrapper(App);

OktWrapper.jsx

    function OktaWrapper(WrapperComponent) {
    const oktaAuth = new OktaAuth(oktaAuthConfig);
    function HOC() {
        const navigate = useNavigate();
        const restoreOriginalUri = () => {
            navigate('/');
        };

        const customAuthHandler = () => {
            navigate('/login');
        };
        return (
            <Security
                oktaAuth={oktaAuth}
                restoreOriginalUri={restoreOriginalUri}
                onAuthRequired={customAuthHandler}
            >
                <WrapperComponent oktaAuth={oktaAuth} />
            </Security>
        );
    }
    return HOC;
}

export default OktaWrapper;

index.js

    const root = document.getElementById('root');
ReactDOM.render(
  <React.StrictMode>
     <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>,
  root
);
reportWebVitals();

Real Time Data For Payoffchart Chart Responsive issue

I am using class based react application..

From the main component i was passing the data as chartdata and i was using real time data where data is passing continusly and i need to provide smooth hover and responsive for payoffchart component

Can anyone provide me the code with responsive

PayoffChartComponent.tsx

import Highcharts, { color } from 'highcharts';
import HighchartsReact from 'highcharts-react-official';
import HighchartMore from 'highcharts/highcharts-more'
import { Button } from 'primereact/button';
import * as math from 'mathjs';
import { Utility } from '../../utils/Utility';
import { Calendar, Checkbox, Dropdown, InputNumber, InputText } from 'primereact';
import { WhatIf } from '../../entity/OptData';
import moment from 'moment';
import { PLCalc } from '../../utils/PLCalc';
import 'highcharts/modules/accessibility';


import * as fs from 'fs';

HighchartMore(Highcharts)
interface Props {
    passedStateData,
    callback,
    callbackShow
}

interface State {
    price;
    farprice;
    IV;
    days;
    finalPrice;
    finalIV;
    finalDays;
}

export class PayoffChartComponent extends React.Component<Props, State> {
    whatif: WhatIf = new WhatIf();

    constructor(props) {
        super(props);

        this.state = {
            price: 0,
            farprice: 0,
            IV: 0,
            days: 0,
            finalPrice: 0,
            finalIV: 0,
            finalDays: 0,
            // spotPrice: this.props.spotPrice
        };

        this.whatif.days = 0;
        this.whatif.IV = 0;
        this.whatif.price = 0;
        this.whatif.allowLegAdjustment = false;
    }


    render() {

        if (this.props.passedStateData.chartData == null) return null;
        if (this.props.passedStateData.legEntityList.length == 0) return null;
        let lastUpdate = this.props.passedStateData?.expiryDataMap[this.props.passedStateData?.selectedExpiryDate]?.lastUpdate;
        let spotPrice = this.props.passedStateData?.expiryDataMap[this.props.passedStateData?.selectedExpiryDate]?.spotPrice;
        if (spotPrice === undefined) return null;

        const { chartData, legEntityList, fundsRequired, selectedsymbol, latestRefreshDate } = this.props.passedStateData;

        // console.log("fundsReq",fundsRequired)




        if (this.whatif.days == 0) {
            let formattedDateTime = new Date(latestRefreshDate);
            formattedDateTime.setSeconds(formattedDateTime.getSeconds() + 1);


            this.whatif.days = formattedDateTime;
            //this.whatif.days = this.props.passedStateData.latestRefreshDate;

        }
        if (this.whatif.days < lastUpdate) {
            let formattedDateTime = new Date(lastUpdate);
            formattedDateTime.setSeconds(formattedDateTime.getSeconds() + 1);

            this.whatif.days = formattedDateTime;
        }


        let arr1 = [];
        let arr2 = [];


        let xAxisData = chartData[0] as Array<number>;
        let len = xAxisData.length;
        const sd = chartData[3]?.sd || 0;
        const farprice = chartData[5]?.farprice || 0;

        // Update whatif days if needed
        if (!this.whatif.days || this.whatif.days < lastUpdate) {
            let formattedDateTime = new Date(lastUpdate);
            formattedDateTime.setSeconds(formattedDateTime.getSeconds());
            this.whatif.days = formattedDateTime;
        }

        // Calculate expiration info
        const legs = legEntityList;
        const allActiveLegs = legs.filter(p => p.enable !== false);
        const allActiveExitedLegs = allActiveLegs.filter(p => p.exited === true);
        const allNotExitedActiveLegs = allActiveLegs.filter(p => !p.exited);
        const leglistActiveStatus = Utility.expiredLegListArrayStatus(allNotExitedActiveLegs);
        const neareastExp = PLCalc.GetEarliestExpiryDateDMY_v2(legs);
        const minExpiry = moment(neareastExp).format('DDMMMYY').toUpperCase();
        const parsedDate = Utility.parseCustomDate(minExpiry);
        const year = parsedDate.getFullYear();
        const month = (parsedDate.getMonth() + 1).toString().padStart(2, '0');
        const day = parsedDate.getDate().toString().padStart(2, '0');
        const formattedDate = `${year}-${month}-${day}T15:30:00`;
        let isPastDate = new Date(formattedDate) < new Date();

        if (!isPastDate) {
            if (allActiveLegs.length === allActiveExitedLegs.length || leglistActiveStatus === false) {
                isPastDate = true;
            }
        }



        let leftSigma1 = 0;
        let leftSigma2 = 0;
        let rightSigma1 = 0;
        let rightSigma2 = 0;
        if (sd > 0) {
            let sdMul: number = 2 * sd;
            leftSigma1 = parseFloat(spotPrice) - sd;
            leftSigma2 = parseFloat(spotPrice) - sdMul;
            rightSigma1 = parseFloat(spotPrice) + sdMul;
            rightSigma2 = parseFloat(spotPrice) + sd;
        }


        for (let i = 0; i < len; i++) {
            let item1 = [];
            let item2 = [];

            item1.push(chartData[0][i], chartData[1][i]);
            arr1.push(item1);

            item2.push(chartData[0][i], chartData[2][i]);
            arr2.push(item2);
        }


        let options = {
            chart: {
                zoomType: 'xy',
                height: 350,
                spacingBottom: 2,
                spacingTop: 5,
                spacingLeft: 2,
                spacingRight: 2,
            },


            title: {
                text: selectedsymbol,
                margin: 30,
                align: 'center',
                x: 50,
                style: {
                    color: 'black',
                    fontSize: '14px',
                }
            },
            accessibility: {
                enabled: false, // Disables accessibility features
            },
            credits: {
                text: 'iCharts.in',
                href: '/',
                position: {
                    verticalAlign: 'top',
                    y: 25

                },
                style: {
                    fontSize: '13px'
                }
            },

            xAxis: {
                gridLineWidth: 1,
                title: {
                    text: 'Price',
                    style: {
                        fontWeight: 'Bold',
                        color: 'Black'
                    },

                },
                labels: {
                    style: {
                        color: 'black'
                    }
                },

                plotBands: [{
                    color: 'rgba(197, 210, 200,0.1)',
                    from: leftSigma1, // Start of the plot band
                    to: rightSigma1, // End of the plot band
                    label: {
                        text: '-1σ',
                        y: -18,
                        align: 'left',
                        style: {
                            color: '#606060'
                        }
                    }
                }
                    , {

                    color: 'rgba(197, 210, 200,0.1)',
                    fillOpacity: 0.2,
                    from: leftSigma1, // Start of the plot band
                    to: rightSigma1, // End of the plot band
                    label: {
                        text: '+2σ',
                        y: -18,
                        align: 'right',
                        style: {
                            color: '#606060'
                        }
                    }
                },
                {

                    color: 'rgba(197, 210, 200,0.1)',
                    from: leftSigma2, // Start of the plot band
                    to: rightSigma2, // End of the plot band

                    label: {
                        text: '-2σ',
                        // x: 100,
                        y: -18,
                        align: 'left',
                        // rotation: -45,
                        style: {
                            color: '#606060'
                        }
                    }
                },
                {

                    color: 'rgba(197, 210, 200,0.1)',
                    from: leftSigma2, // Start of the plot band
                    to: rightSigma2, // End of the plot band
                    label: {
                        text: '+1σ',
                        // x: 100,
                        y: -18,
                        align: 'right',

                        style: {
                            color: '#606060'
                        }
                    }
                }],
                plotLines: [
                 
                    {
                        color: 'red',
                        fillOpacity: 0.2,
                        lineWidth: 3,
                        dashStyle: 'shortdot',
                        zIndex: 3,
                        value: spotPrice,
                        label: {
                            text: spotPrice,
                            rotation: 0,
                            x: -20,
                            y: 0,
                            style: {
                                fontSize: '11.5px',
                                color: '#606060'
                            }
                        }
                    }
                ],
                crosshair: {
                    label: {
                        enabled: true,

                        padding: 8
                    }
                }
            },

            yAxis: [

                {
                    gridLineColor: 'rgba(50,205,50,0.15)',
                    startOnTick: false,
                    lineWidth: 1,

                    title: {
                        text: 'P/L',
                        style: {
                            fontWeight: 'Bold',
                            color: 'Black'
                        },
                    },
                    labels: {

                        style: {
                            color: 'black'
                        },

                    },
                    crosshair: {
                        label: {
                            enabled: true,
                        },
                        dashStyle: 'longdash',
                        color: 'gray',
                    },

                    plotLines: [{
                        value: 0,
                        width: 2,
                        color: '#aaa',

                    }],


                },
                { // Secondary yAxis

                    gridLineColor: 'rgba(50,205,50,0.15)',

                    lineWidth: 1,
                    startOnTick: false,
                    endOnTick: false,
                    title: {
                        text: '',
                        style: {
                            fontWeight: 'Bold'
                        },
                    },
                    label: {
                        enabled: true,
                    },

                    opposite: true,
                }


            ],

            legend: {
                align: 'right',
                verticalAlign: 'top',

            },
            
            tooltip: {
                useHTML: true, // Allows custom HTML content
                shared: true, // Show shared tooltip
                borderColor: 'grey', // Set border color to grey
                borderWidth: 1, // Set border width for better visibility
                backgroundColor: 'white', // Optional: Set background color to white
                
                formatter: function (this: Highcharts.TooltipFormatterContextObject) {
                    let xaxisPoint: any = this.x;
                    const percentageChange = (((xaxisPoint) / spotPrice) - 1) * 100;
                    const percentageColor = percentageChange > 0 ? '#02d302' : (percentageChange < 0 ? 'red' : 'black');

                    let rupeeSymbol = '₹';

                    return ` 
                    <b>${this.x} (<span style="color:${percentageColor}">${percentageChange.toFixed(2)}%</span>)</b><br/>
                    ${this.points
                            ?.map(
                                point => {
                                    // Round point.y to the nearest integer
                                    const roundedY = Math.round(point.y);

                                    const fundRequired = fundsRequired !== 0.00 || fundsRequired !== 0 ? `(${((roundedY / fundsRequired) * 100).toFixed(2)}%)` : ``;


                                    return `
                        <span style="color:${point.color}">u25CF</span> ${point.series.name}: 
                        <b>${roundedY > 0 ? `<span style="color:#02d302;fontSize:10px;fontFamily: "Helvetica","Arial",sans-serif;">${rupeeSymbol} ${roundedY} ${fundRequired}</span>` :
                                            (roundedY === 0 ? `<span style="color:black;fontSize:10px;fontFamily: "Helvetica","Arial",sans-serif;">${rupeeSymbol} ${roundedY} ${fundRequired}</span>` : `<span style="color:red;fontSize:10px;fontFamily: "Helvetica","Arial",sans-serif;">${rupeeSymbol} ${roundedY} ${fundRequired}</span>`)
                                        } 
                            </b><br/>`;
                                })
                            .join('') || ''}
                `;
                },
                valueDecimals: 2, // Specify decimal places for numbers
            },


            series: [{
                showInLegend: false,
                type: 'line',
                name: 'T+0',
                data: arr1,
                color: 'rgb(0,0,255)',
                fillOpacity: 0.1,
                connectNulls: true,
                lineWidth: 1.5,
                dashStyle: 'shortdot',
                marker: {
                    enabled: false
                }
            }, {
                type: 'area',
                name: 'Expiry',
                fillOpacity: 0.1,
                showInLegend: false,
                negativeColor: 'rgb(255,127,127)',
                color: 'rgb(50,205,50)',
                data: arr2,
                connectNulls: true,
                lineWidth: 1.5,
                marker: {
                    enabled: false
                }
            },
            ]

        };

        return <div key={'payoffChart_' + selectedsymbol + this.props.passedStateData.selectedExpiryDate}>
            <div style={{ display: this.props.passedStateData.chainShowed ? 'none' : 'flex' }} className='alignedLeft' >Option Chain<img src='./show_left.svg' onClick={this.props.callbackShow}></img></div>
            <div className='border-chat'>
                <HighchartsReact highcharts={Highcharts} options={options} containerProps={{ style: { hight: '100%', width: '100%' } }} />
            </div>
            <div>
                <div className="main-check">
                    <div className='checkbox-allow'>
                        <Checkbox inputId="allowId"
                            disabled={isPastDate}
                            checked={this.whatif.allowLegAdjustment} onChange={(e) => {
                                this.whatif.allowLegAdjustment = e.checked;
                                this.whatif.IV = 0;

                                this.props.callback(this.whatif);
                            }} />
                        {/* <label htmlFor="allowId">Allow  Leg IV Adjustments</label> */}
                        <label style={{ color: isPastDate ? 'grey' : 'black' }} htmlFor="allowId">Allow Leg IV Adjustments</label>

                    </div>

                    <div className="leglot-dropdown">
                        <InputNumber
                            disabled={isPastDate}
                            value={this.whatif.price}

                            onInput={(e) => {
                                let inputValue = e.value || e.target?.value || "";

                                const newValue: number = inputValue;
                                const oldValue: number = this.whatif.price;
                                const isIncrement = newValue > oldValue;

                                this.whatif.price = newValue;
                                let fp = this.getFarprice(farprice, isIncrement, newValue)

                                this.whatif.farprice = fp;
                                this.setState({ price: newValue, farprice: fp },
                                    () => this.props.callback(this.whatif))
                            }}


                            onValueChange={(e) => {
                                // console.log(spotPrice)

                                const newValue: number = e.value;
                                const oldValue: number = this.whatif.price;
                                const isIncrement = newValue > oldValue;

                                this.whatif.price = newValue;
                                let fp = this.getFarprice(farprice, isIncrement, newValue)

                                this.whatif.farprice = fp;
                                // console.log(this.whatif)
                                // prefix={`${spotPrice}`}
                                // prefix={`${spotPrice.toFixed(2)}`}
                                // prefix = {`${spotPrice.toFixed(2)} (0.1%)`}

                                this.setState({ price: newValue, farprice: fp },
                                    () => this.props.callback(this.whatif))
                            }


                            } showButtons
                            buttonLayout="horizontal" step={0.1} prefix={`${spotPrice}   `} max={20} min={-20}
                            decrementButtonClassName="p-button-danger" incrementButtonClassName="p-button-success" incrementButtonIcon="pi pi-plus" decrementButtonIcon="pi pi-minus" suffix="%"
                        />
                    </div>


                    <div className="leglot-dropdown">
                        <Calendar value={this.whatif.days}
                            disabled={isPastDate}
                            onChange={(e) => {
                                // console.log(this.whatif.days)
                                // console.log(e.value)
                                // console.log(formattedDate)

                                this.whatif.days = e.value;
                                // this.setState({ days: e.value },
                                //     () => this.props.callback(this.whatif))
                                // console.log(this.whatif.days);

                                this.setState({ days: e.value }, () => this.props.callback(this.whatif))

                            }}

                            //`${year}-${month}-${day}

                            //  showTime hourFormat="12" dateFormat="dd/mm/yy" maxDate={new Date(formattedDate)} minDate={new Date()}/>

                            showTime hourFormat="12" dateFormat="dd/mm/yy" maxDate={new Date(formattedDate)} minDate={new Date()} />
                    </div>


                    <div className="leglot-dropdown" >
                        <InputNumber value={this.whatif.IV} disabled={this.whatif.allowLegAdjustment || isPastDate} onValueChange={(e) => {
                            this.whatif.IV = e.value;
                            // console.log(this.whatif)
                            this.setState({ IV: e.value },
                                () => this.props.callback(this.whatif))
                        }
                        }
                            onInput={(e) => {
                                let inputValue = e.value || e.target?.value || "";

                                this.whatif.IV = inputValue;
                                // console.log(this.whatif)
                                this.setState({ IV: inputValue },
                                    () => this.props.callback(this.whatif))
                            }}
                            showButtons
                            buttonLayout="horizontal" step={1} prefix='IV  ' max={20} min={-20}
                            decrementButtonClassName="p-button-danger" incrementButtonClassName="p-button-success"
                            incrementButtonIcon="pi pi-plus" decrementButtonIcon="pi pi-minus" suffix="%" />
                    </div>
                    <div>
                        <Button label="Reset" className="p-button-primary smallButton" onClick={() => {
                            this.setState({
                                price: 0,
                                IV: 0,
                                days: 0,
                                finalPrice: 0,
                                finalIV: 0,
                                finalDays: 0
                            }, () => {

                                // console.log(this.props.passedStateData.lastUpdate)
                                let formattedDateTime = new Date(lastUpdate);


                                formattedDateTime.setSeconds(formattedDateTime.getSeconds() + 1);

                                // console.log('formattedDateTime reset',formattedDateTime)
                                this.whatif.days = formattedDateTime;
                                // this.whatif.days = this.props.passedStateData.markethours;
                                this.whatif.price = 0;
                                this.whatif.farprice = farprice;
                                this.whatif.IV = 0;
                                this.whatif.allowLegAdjustment = false;
                                legEntityList.forEach(p => p.iv_adjustment = null);
                                let Reset = true;
                                // this.props.callback(this.whatif,this.props.passedStateData.legEntityList,Reset)
                                if (this.props.passedStateData.whatif !== null) this.props.callback(this.whatif, legEntityList, Reset)

                            });
                        }} />
                    </div>
                </div>



            </div>
        </div>
    }


    getFarprice = (farprice, isIncrement, newPrice) => {
        let farPrice: any;
        if (isIncrement) {
            // alert()
            farPrice = parseFloat(farprice + (farprice * newPrice) / 100).toFixed(2);
        } else {
            farPrice = farprice - (farprice * newPrice) / 100;
        }

        return farPrice;

    }


    GetFarExp = (legs) => {

        let mexpdt = '';

        legs.forEach(optleg => {
            let legdt: string = optleg.Expiry
            if (mexpdt == "" || Utility.parseFormattedCustomDate(legdt) > Utility.parseFormattedCustomDate(mexpdt)) {
                mexpdt = optleg.Expiry;
            }
        });

        // console.log(mexpdt);

        return mexpdt;
    }
}






Problem installing tailwindcss in my project [duplicate]

Could someone help me correct this error.

I was hoping to install and use tailwindcss in my project

npx tailwindcss init

npm error could not determine executable to run
npm error A complete log of this run can be found in: C:UsersPC lenovoAppDataLocalnpm-cache_logs2025-05-29T07_28_09_340Z-debug-0.log