Server sent events in pedestal returns empty response

I am currently implementing server sent events (SSE) in an web application using Clojure, Pedestal and Jetty.

When I print the message in the backend the channel is open and when I invoke io.pedestal.http.sse/send-event it returns true, however in the frontend I get no console.log() prints in Javascript in the browser console. as if there is no data received. I tested the SSE connection in Postman and it is successful but the response is (empty).

Backend:

    (def SSE-REGISTRY (atom {}))
     
     (defn get-user-channel [token]    
       (get @SSE-REGISTRY token))
     
     (defn test-print [channel]    
       (println "channel:" channel) ;; channel:#object[clojure.core.async.impl.chan...]   
       (println "channel opened:" (not (chan/closed? channel))) ;; channel opened: true  
       (println "sent-event:" 
       (sse/send-event channel "status"
         (json/write-str {:id 1
                          :workflowId 3
                          :status :GOOD}) ;; sent-event: true
     
     (defn send-sse-msg [name data id]   
       (when-let [sse-channels (vals @SSE-REGISTRY)]
         (doseq [channel sse-channels] 
           (when-not (chan/closed? channel)
             (test-print channel)
             (sse/send-event channel name data id)))))   

(def sse-route ["/rest/sse" :get 
                  (sse/start-event-stream send-sse-msg 10 100) 
                  :route-name :sse])
     
     (defn create-sse-channel []   
        (async/chan (async/sliding-buffer 100)))

enter image description here

Frontend:

 const protocol = window.location.protocol;
const host = window.location.port; 
const sseUrl = protocol + '//'+ host + '/rest/sse';
const RUN_BUTTON_STATUS_TIME = 2000;
const sseInitOptionsMap = {
                            headers: {
                                       'Content-Type': 'text/event-stream; charset=utf-8',
                                       'Connection': 'keep-alive', 
                                       'Cache-Control': 'no-cache' 
                                      },
                            withCredentials: true,
                            https: {rejectUnauthorized: true}
                          };

export const eventSource = new EventSource(sseUrl, sseInitOptionsMap);
eventSource.addEventListener('integrationStatus', sendStatusHandler);
eventSource.addEventListener('stopAction', sendStopActionHandler);

eventSource.onopen = (e) => {
  console.log("SSE connection opened:" + e);
};

eventSource.onerror = (e) => {
  console.log("error:" + e);
  if (e.readyState == EventSource.CLOSED) {
      console.log("connection closed:" + e);
  } else {
    eventSource.close();
    console.log("SSE connection closed:" + e);
  }
};

export function sendStatusHandler(event) {
  const data = JSON.parse(event.data);
  console.log("data:" + data);
  let id = data.id;
  let workflowId = data.workflowId;
  let status = data.status;
  cljsDisp("set-global-operation-status", id, workflowId, status);
  configurtorActionRunButtonStatus(id, workflowId, status);
  setTimeout(cljsDisp("get-last-run-action-data", id, workflowId, status),
             300);
}

function configurtorActionRunButtonStatus (id, workflowId, status) {
  if (status === "GOOD") {
    showStatus(id, workflowId, true);
  } else if (status === "BAD") {
    showStatus(id, workflowId, true);
    cljsDisp("configurator-error-message-show", id, workflowId, true);
  } else {
    cljsDisp("configurator-action-run-button-status-visible?", id, workflowId, false);
  }
}

export function sendStopWorkflowHandler(event) {
  const data = JSON.parse(event.data);
  console.log("data:" + data); // prints nothing
  let workflowId = data.workflowId;
  cljsDisp("stop-action-by-sse-msg", workflowId);
}

function showStatus(integrationId, operationId, showStatus) {
  setTimeout(cljsDisp("configurator-action-run-button-status-visible?", 
                      integrationId, operationId, showStatus),
             RUN_BUTTON_STATUS_TIME);
}

export function closeSse() {
  if (eventSource.readyState != eventSource.CLOSED) {
    eventSource.close();
  }
}

enter image description here

It seems I am missing something. Can you help. The problem is that there are not much examples of Clojure with Pedestal implementation of SSE. Most are in JavaScript and other languages.

Default Value in a select box (MUI) not showing unless an onChange event is fired

I am fetching data from an API in order to render a Select box. The value in the select box contains a users details. My problem is that on initial load even when data is fetched correctly a default / initial user is not rendered within the select box even though the data is there.

The onchange event and the select box itself works as expected otherwise. I have added a default value. A key to show the DOM its a new element and unsure what else to try

import { Avatar, Grid, MenuItem, SelectChangeEvent, Select } from "@mui/material";
import {iconMap} from './iconMap.ts'

const SocialSelectDropdown = () => {

    const [selectedAccount, setSelectedAccount] = useState<IConnectionData | null>(connectionData?.[0] ?? null)

    useEffect(() => {
        if (connectionData) {
            setSelectedAccount(connectionData?.[0])
        }
    }, [connectionData])

    const handleSelectedConnection = (e: SelectChangeEvent<string | unknown>) => {
        setSelectedAccount((prevState: IConnectionData | null) => {
            const selectedSocial = connectionData?.find((connection) => connection?.id === e?.target?.value);
            return selectedSocial || prevState;
        });
    };


    if (!selectedAccount?.id) {
        return <Loader />
    }

    return (
        <Grid item xs={12}>
            <Select
                key={selectedAccount?.id}
                size="small"
                sx={{ maxWidth: "fit-content" }}
                value={selectedAccount?.id}
                onChange={handleSelectedConnection}

            >
                {connectionData
                    ?.filter((item: any) => !["facebook_user"].includes(item?.platform))
                    ?.filter((item) => (role_id === 5 ? item : item?.platform !== "linkedin"))
                    ?.map((social: IConnectionData, index: number) => (
                        <MenuItem key={social?.id} selected={selectedAccount?.id === social?.id} value={social.id}>
                            <Grid container flexDirection="row" alignItems="center" gap={1}>
                                <Grid item position="relative">
                                    <Avatar src={social?.profile_pic_url} />
                                    <Grid item position="absolute" bottom={-5} right={-5}>
                                        <GetPlatformIcon platform_id={iconMap(social)} size={20} />
                                    </Grid>
                                </Grid>
                                <Typography>
                                    {social?.username}
                                </Typography>
                            </Grid>
                        </MenuItem>
                    ))}
            </Select>
        </Grid>
    );
};

export default SocialSelectDropdown

wn;

Are anonymous functions optimized in node.js

Let’s take this stupid piece of code as an example

for (let i = 0; i < 10; i++) {
  console.log(
    (function (x) {
      if (x % 2) {
        return 'even';
      } else {
        return 'odd';
      }
    })(i)
  );
}

Basically, we have an anonymous function that is called multiple times inside a loop, or maybe inside another function.
I wonder if it is recreated on every iteration of the cycle or is it optimized somehow?
I would appreciate if you could give me a hint on how to find this kind of things on my own.
Thanks!

How can I make my code not dependent on the user’s timezone?

I am making a simple website that displays how long it has been since the last “red alert” in Israel. It uses this API: https://agg.rocketalert.live/api/v1/alerts/details. When testing with BrowserStack, I noticed that the time since the last alert is different depending on what time zone the user is in. How can I negate this and make it so that the time since last alert is the same for all users?

// Velo API Reference: https://www.wix.com/velo/reference/api-overview/introduction
// counter.js

// API endpoint URL
const apiUrl = 'https://agg.rocketalert.live/api/v1/alerts/details';

// Counter container
const counterContainer = $w('#counter')

// Function to fetch data from the API and update the counter
function updateCounter() {
    fetch(apiUrl)
        .then(response => {
            if (!response.ok) {
                throw new Error(`Network response was not ok: ${response.status} ${response.statusText}`);
            }
            return response.json();
        })
        .then(data => {
            // Extract the payload array from the response
            const payload = data.payload;

            // Sort the dates in descending order
            const sortedDates = payload.map(dateObj => dateObj.date).sort((a, b) => new Date(b) - new Date(a));

            // Get the latest date
            const latestDate = sortedDates[0];

            // Get the alerts for the latest date
            const alertsForLatestDate = payload.find(dateObj => dateObj.date === latestDate).alerts;

            // Sort the alerts in ascending order by timestamp (since they are listed last)
         
       const latestrecord = alertsForLatestDate.sort((a, b) => new Date(b.timeStamp) - new Date(a.timeStamp))[0];

       const latesttimestamp =latestrecord.timeStamp;
const latestAlertTimestamp = new Date(latesttimestamp).getTime();

const utcOffsetInMilliseconds = -7 * 60 * 60 * 1000; 
const adjustedTimestamp = latestAlertTimestamp + utcOffsetInMilliseconds;


const currentTime = Date.now(); 
            const timeDifferenceMs = currentTime - adjustedTimestamp;

            // Convert milliseconds to years, days, hours, minutes, and seconds
            const years = Math.floor(timeDifferenceMs / (1000 * 60 * 60 * 24 * 365));
            const days = Math.floor((timeDifferenceMs % (1000 * 60 * 60 * 24 * 365)) / (1000 * 60 * 60 * 24));
            const hours = Math.floor((timeDifferenceMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
            const minutes = Math.floor((timeDifferenceMs % (1000 * 60 * 60)) / (1000 * 60));
            const seconds = Math.floor((timeDifferenceMs % (1000 * 60)) / 1000);

            // Update the counter text
            counterContainer.text = `${years} years, ${days} days, ${hours} hours, ${minutes} minutes, ${seconds} seconds`;
        })
        .catch(error => {
            console.error('Error fetching data from the API:', error);
        });
}

// Call the updateCounter function initially
updateCounter();
setInterval(updateCounter, 5000);

// Update the counter every second

I tried to add multiple UTC offsets, but they all did nothing to solve the issue of international users seeing different times.

For example, the current 7 hour offset works for my time zone but results in different times depending on where the user is located.

Office JS – how to get bindings to stick in different sessions

I am integrating with a third party app that uses content controls and custom XML parts to store values in Word. I created a function that binds each content control to its respective variable, and it works. Something like this:

 await Office.context.document.bindings.addFromNamedItemAsync(contentControl.title, Office.BindingType.Text, { id: contentControl.title}, (asyncResult) =>
                    this.bindingFunction(asyncResult, context, contentControl, fieldName, fieldValue));

“bindingFunction” basically creates a few event handlers if a content control is modified for some math and other updates. The problem I’m running into is that this binding function takes almost a minute to run over the entire document upon opening – it’s a 10+ page document with hundreds of content controls. If I don’t call on the function on init, the bindings are gone the moment I close and reopen the document. Is there a quick way to save the bindings and just reapply them when the app/pane opens instead of having to get all content controls and run the binding function every time?

I tried getting the bindings and storing them:

   Office.context.document.bindings.getAllAsync(async (result) => {
        if (result.status === Office.AsyncResultStatus.Succeeded) {
          
          this.bindings = result.value.map(binding => {
            return {
              id: binding.id,
              data: binding.document.bindings
            };
          });

However, when I reopen it, this info doesn’t seem to be enough to reapply the bindings.

Undefined problem when fetching and array [duplicate]

I have a .json array that contains objects, I fetch that array from the .json and save it to an array in my .js file.

[
  {
    "id": 1,
    "name": "Burton Family Tree",
    "price": 600,
    "img": "url"
  },
  {
    "id": 2,
    "name": "Burton Mystery",
    "price": 700,
    "img": "url"
  },
 .
 .
 .
]

When I use the complete fetched array it works perfectly but when I want to use just one element of this array it shows an undefined error for the whole object itself and each attribute of it.

let products = [];
let productsURL = url;

async function loadProducts() {
  try {
    const response = await fetch(productsUrl);
    const productsJSON = await response.json();
    for (const item of productsJSON) {
      products.push({
        name: item.name,
        price: item.price,
        img: item.img,
      });
    }
  } catch (error) {
    console.log(error);
  }
}

loadProducts();

console.log(products) -> works fine

console.log(products[0]) -> Uncaught Type Error: Cannot read properties of undefined

console.log(products[0].img) -> Uncaught Type Error: Cannot read properties of undefined (reading 'img')`

How to build the “dist” in Node.js project

Here is the Leaflet Routing Machine:

https://github.com/perliedman/leaflet-routing-machine

The “main” in “package.json” is “./dist/leaflet-routing-machine.js“, but the real source file in the project is “src/index.js“.

Here is the “package.json”:
https://github.com/perliedman/leaflet-routing-machine/blob/master/package.json

{
  "name": "leaflet-routing-machine",
  "version": "3.2.12",
  "description": "Routing for Leaflet",
  "directories": {
    "example": "examples",
    "dist": "dist"
  },
  
  "main": "./dist/leaflet-routing-machine.js",
  
  "dependencies": {
    "@mapbox/corslite": "0.0.7",
    "@mapbox/polyline": "^0.2.0",
    "osrm-text-instructions": "^0.13.2"
  }
}

Here is the “src/index.js”:
https://github.com/perliedman/leaflet-routing-machine/blob/master/src/index.js

var L = require('leaflet'),
    Control = require('./control'),
    Itinerary = require('./itinerary'),

I’m creating my first node.js project, I think the “main” should be like this:

"main": "src/index.js"

What command is used to build the “./dist/leaflet-routing-machine.js” in the “Leaflet Routing Machine” project?

Why style property is not working in javascript

I am a beginner and I am learning JavaScript now. I am trying to make a javascript game. On this project, I am trying to add a style through javascript. On my project, there is a div named “Chick”. When user press any key the row and column will change for the chick. But the style is not working. The style is not added when I press key.

 const chick = document.querySelector('.chick');
let chickRow = 17;
let chickCol = 10;

document.addEventListener('keydown', (e) => {
    if ((e.key === "ArrowUp") && (chickRow > 0)) {
        chickRow -= 1;
    }
    if ((e.key === "ArrowDown") && (chickRow < rows)) {
        chickRow += 1;
    }
    if ((e.key === "ArrowLeft") && (chickCol > 0)) {
        chickCol -= 1;
    }
    if ((e.key === "ArrowRight") && (chickCol < columns)) {
        chickCol += 1;
    }

    chick.style.gridArea= `${chickRow} / ${chickCol}`;
});

how do i do a image display form

I want an image found referring to the person that was searched for (in the people table) to be presented in the html, but at the same time I want it so that if the user wants to change the photo, he just needs to click on it of the image already presented and then the file explorer is opened so that a new image can be chosen. Once the new image has been chosen, the new image must be displayed in the html in place of the old one temporarily.
the program is opening the file explorer, i choose the new image but the old image isn’t change and the new image isn’t displayed in any place of the html too
my code:

<script>

// Quando a imagem da pessoa for clicada
document.getElementById("imagem-pessoa").addEventListener('click', function() {
// Abrir o explorador de arquivos ao clicar no campo de arquivo oculto
document.getElementById("input-imagem").click();
});

// Quando uma nova imagem for selecionada
document.getElementById("input-imagem").addEventListener('change', function(event) {
// Capturar a nova imagem selecionada
const novaImagem = event.target.files[0];
// Atualizar temporariamente a imagem no HTML
const urlNovaImagem = URL.createObjectURL(novaImagem);
document.getElementById("imagem-pessoa").src = urlNovaImagem;
});
</script>

and the html

<img class="rectangle" id="imagem-pessoa" src="{{ pessoa.imagem.url }}" alt="Imagem da Pessoa">>
<input type="file" id="input-imagem" style="display: none;" accept="image/*">

it aren’t working

i tried a lot of things that chatgpt say a many of them make sense, but still don’t work.
what i expected is: “a person registration page is loaded, receiving a number that searches the database and returns a person from the database. It then fills in some elements on the screen with the data found in the database table about that person. Among the people model objects there is a model.ImageField that stores a photo of each person.” What I need is: I want the image found referring to the person that was searched for (in the people table) to be presented in the html, but at the same time I want it so that if the user wants to change the photo, he just needs to click on it of the image already presented and then the file explorer is opened so that a new image can be chosen. Once the new image has been chosen, the new image must be displayed in the html in place of the old one temporarily, but the replacement of the photo in the database must only be carried out after a submit button is clicked

AceEditor’ cannot be used as a JSX component. Its type ‘typeof ReactAce’ is not a valid JSX element type

I have this project that mostly uses jsx extensions despite being setup with typescript. When creating a new component, I decided to go with the tsx extension and ran into this error:

'AceEditor' cannot be used as a JSX component.
  Its type 'typeof ReactAce' is not a valid JSX element type.
    Types of construct signatures are incompatible.
      Type 'new (props: IAceEditorProps) => ReactAce' is not assignable to type 'new (props: any, deprecatedLegacyContext?: any) => Component<any, any, any>'.
        Construct signature return types 'ReactAce' and 'Component<any, any, any>' are incompatible.
          The types returned by 'render()' are incompatible between these types.
            Type 'Element' is not assignable to type 'ReactNode'.ts(2786)

I searched and found nothing and tried type assertion: as unknown as JSX.Element, but that didn’t work either.

My code:

import React from 'react';
import AceEditor from 'react-ace';

// Import necessary modes and themes from ace-builds
import 'ace-builds/src-noconflict/mode-javascript';
import 'ace-builds/src-noconflict/mode-python';
// Add more modes here as needed

import 'ace-builds/src-noconflict/theme-github'; // You can change the theme if you wish
import 'ace-builds/src-noconflict/theme-monokai'; // You can change the theme if you wish

interface CodeEditorProps {
    language: string;
    starterCode: string;
    code: string;
    onChange: (newValue: string) => void;
    fontSize?: number; // Make fontSize an optional prop
}

const CodeEditorAce: React.FC<CodeEditorProps> = ({
    language,
    starterCode,
    code,
    onChange,
    fontSize = 14,
}) => {
    // Default fontSize is set to 14, but can be overridden by props

    const getMode = (language: string) => {
        switch (language.toLowerCase()) {
            case 'javascript':
                return 'javascript';
            case 'python':
                return 'python';
            // Add more cases for other languages you support
            default:
                return 'text';
        }
    };

    let value = code ? code : starterCode;

    return (
        <AceEditor
            placeholder="Do not edit the starter code."
            mode={getMode(language)}
            theme="monokai"
            value={value}
            onChange={onChange}
            name={`code-editor-${Math.random()}`} // Ensures a unique ID
            editorProps={{ $blockScrolling: true }}
            showPrintMargin={true}
            showGutter={true}
            highlightActiveLine={true}
            setOptions={{
                enableBasicAutocompletion: true,
                enableLiveAutocompletion: true,
                enableSnippets: true,
                showLineNumbers: true,
                tabSize: 2,
            }}
            fontSize={fontSize} // Set the font size here
            height="100%"
            width="100%"
        />
    );
};

export default CodeEditorAce;

I also get the same issue if I use code mirror instead of Ace Editor:

'CodeMirror' cannot be used as a JSX component.
  Its type 'ForwardRefExoticComponent<ReactCodeMirrorProps & RefAttributes<ReactCodeMirrorRef>>' is not a valid JSX element type.
    Type 'ForwardRefExoticComponent<ReactCodeMirrorProps & RefAttributes<ReactCodeMirrorRef>>' is not assignable to type '(props: any, deprecatedLegacyContext?: any) => ReactNode'.
      Type 'ReactElement<any, string | JSXElementConstructor<any>> | null' is not assignable to type 'ReactNode'.ts(2786)
        "react": "^18.2.0",
        "react-ace": "^10.1.0",
        "ace-builds": "^1.32.7",
        "react-dom": "^18.2.0",

I installed the types for ace and didn’t do much either.

canvg canvas getting slower with each edit/ memory usage increase

I have developed a scientific application to measure the area of shapes drawn on a scanned paper using canvg (version 3. something). The application works mostly fine (in Chrome), but gets really slow after a lot of small areas are selected.

var s = canvg('canvas', inp_xmls, {ignoreMouse: true, ignoreAnimation: true});

Each click inside an area performs a bucket fill using the canvg bucket-fill:

var bucket = Bucket(canvas, cfg, event, color);

Subsequently, the image is updated to view the new filled area:

    var lowerimg = svg.image(can.toDataURL());
    console.log(lowerimg)

    lowerimg.node.onload = function () {
        drawDown();

function drawDown() {
    inp_xmls = XMLS.serializeToString(svg.node);
    s.loadXml(ctx, inp_xmls);
    s.stop();
}

function undo() {
    var last = svg.last();

    if(svg.index(last) > 1) {
        last.remove();
        drawDown();
        s.draw();
    }
    undoAddArea();
}

Using the memory snapshots I can see ‘strings’ are increasing in size significantly (and image + #document).

The application is available online here:
https://limo.mni.thm.de/
Clicking on “Beispiel” on the right open an example slide in the drawing board.

My questions:

  • How can I reduce memory usage of the filling/ drawing on the canvas? Is there a function in canvg to ‘clear’ older layers?
  • I need the possibility to ‘undo’ clicks, so I need to store some of them. How do I access the old images like in the ‘undo’ function to remove everything older than 5 edits for example?

I need the pause and play functionality of the lightningchart lib curves in JavaScript

enter image description here
The back sends me an array of numbers and I take these numbers and display the ‘ECG’ type curves in the same way as in the documentation, perfect! This works, but I need the functionality to pause (stop the display of the curves) and play (unlock the display of the curves and the function continues consuming the array of numbers where it was paused). I’m asking you to help me with this… do you have a ready-made feature? If not, could you give me an idea of how to do it?

I tried this output from this example:
https://github.com/Arction/lcjs-showcase-audio
But unfortunately without success

React table updating with websocket

I have connection to WebSocket that sends me a message every 0.1s, than i write it to useState. Then react rerender whole table with new element. Is there any method to add new element to table or a part of a table, avoiding rerendering of all other elements?

I tried to use MillionJS library to optimise table rendering, but it’s not enough. It continue rerendering the whole table