How could connect WebSocket Server(STOMP)

I’m using Stomp WebSocket and can’t connect to Server

package study.withkbo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
    // https://docs.spring.io/spring-framework/reference/web/websocket/stomp/overview.html
    // https://www.toptal.com/java/stomp-spring-boot-websocket

    private TaskScheduler messageBrokerTaskScheduler; 

    @Autowired
    public void setMessageBrokerTaskScheduler(@Lazy TaskScheduler taskScheduler) {
        this.messageBrokerTaskScheduler = taskScheduler;
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/portfolio") 
                .setAllowedOrigins("*")
                .withSockJS(); 
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.setApplicationDestinationPrefixes("/app");
        config.enableSimpleBroker("/topic", "/queue") 
                .setHeartbeatValue(new long[] {10000, 20000}) 
                .setTaskScheduler(this.messageBrokerTaskScheduler);
    }
    @Bean
    public ServletServerContainerFactoryBean createWebSocketContainer() {
        ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
        container.setMaxTextMessageBufferSize(8192); // 8KB
        container.setMaxBinaryMessageBufferSize(8192);
        return container;
    }

    @Override
    public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
        registry.setTimeToFirstMessage(30000); 
        registry.setSendTimeLimit(15 * 1000).setSendBufferSizeLimit(512 * 1024);
        registry.setMessageSizeLimit(128 * 1024); 
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new ChannelInterceptor() {
            @Override
            public Message<?> preSend(Message<?> message, MessageChannel channel) { 
                StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
                if (StompCommand.CONNECT.equals(accessor.getCommand())) {
                    // Access authentication header(s) and invoke accessor.setUser(user)
                }
                return message;
            }
        });
    }
}

client service

package study.withkbo.client.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.converter.StringMessageConverter;
import org.springframework.messaging.simp.stomp.StompSessionHandler;
import org.springframework.web.socket.client.WebSocketClient;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.messaging.WebSocketStompClient;
import study.withkbo.client.handler.MyStompSessionHandler;

public class ClientService {

    private WebSocketStompClient stompClient;

    @Value("${websocket.server.url}")
    private String serverUrl;

    public ClientService() {
        WebSocketClient webSocketClient = new StandardWebSocketClient(); 
        WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient); 
        stompClient.setMessageConverter(new StringMessageConverter()); 
        stompClient.setDefaultHeartbeat(new long[]{10000, 20000}); 
        connect();
    }

    public void connect() {
        StompSessionHandler sessionHandler = new MyStompSessionHandler(); 
        stompClient.connect(serverUrl, sessionHandler);
    }
}

application.yaml

jwt:
  secret:
    key: +==
  access:
    expiration: 3600000

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/
    username: root
    password: 
    driver-class-name: com.mysql.cj.jdbc.Driver
  profiles:
    active: aws
  jpa:
    hibernate:
      ddl-auto: update
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    show-sql: true
    properties:
      hibernate.format_sql: true

websocket:
  server:
    url: ws://127.0.0.1:8080/portfolio

this is vscode to connect front

import React, { useEffect, useState } from "react";
import { Client } from "@stomp/stompjs";
import SockJS from "sockjs-client";
import styled from "styled-components";

const WebSocket = () => {
  const [connected, setConnected] = useState(false);

  useEffect(() => {
    const stompClient = new Client({
      webSocketFactory: () => new SockJS("https://127.0.0.1:8080/portfolio"),
      heartbeatIncoming: 20000,
      heartbeatOutgoing: 10000,
      debug: (str) => console.log("STOMP Debug:", str),
      onConnect: () => {
        setConnected(true);
        console.log("WebSocket connected");
      },
      onDisconnect: () => {
        setConnected(false);
        console.log("WebSocket disconnected");
      },
      onStompError: (frame) => {
        console.error("STOMP error:", frame);
        setConnected(false);
      },
      onWebSocketClose: (event) => {
        console.error("WebSocket close:", event);
      },
    });

    stompClient.activate();

    return () => {
      if (stompClient) stompClient.deactivate();
    };
  }, []);
};

export default WebSocket;

const Container = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
`;

Intellij code terminal

2024-11-22T17:44:11.442+09:00  INFO 13888 --- [MessageBroker-1] o.s.w.s.c.WebSocketMessageBrokerStats    : WebSocketSession[0 current WS(0)-HttpStream(0)-HttpPoll(0), 0 total, 0 closed abnormally (0 connect failure, 0 send limit, 0 transport error)], stompSubProtocol[processed CONNECT(0)-CONNECTED(0)-DISCONNECT(0)], stompBrokerRelay[null], inboundChannel[pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], outboundChannel[pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], sockJsScheduler[pool size = 8, active threads = 1, queued tasks = 3, completed tasks = 6]
2024-11-22T17:47:50.814+09:00  WARN 13888 --- [l-1 housekeeper] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Thread starvation or clock leap detected (housekeeper delta=2m12s994ms61µs200ns).

It’s still [https://i.sstatic.net/JfV7ZH2C.png] repeated

I want to make Chatting and solve until this week
It is teamproject so I have to solve quickly
sorry for not good english
I can’t find trobleshooter around me
Using Intellj and VsCode

How to Ensure Input Fields Display Periods Instead of Commas for Decimal Values in Angular?

How should I make the SIP minimum and SIP maximum input fields display values with periods instead of commas (like 50.00 instead of 50,00), please?`

enter image description here

Directive

@Directive({
  selector: '[appCommaToDot]'
})
export class CommaToDotDirective {
  constructor(private el: ElementRef) {}

  @HostListener('input', ['$event'])
  onInputChange(event: Event): void {
    const input = this.el.nativeElement;
    const value = input.value;

    input.value = value.replace(/,/g, '.');
  }
}

ts

export class EditPurchasableSecuritiesComponent implements OnInit, OnDestroy {

  private unsubscribe$ = new Subject < void > ();

  svm: string; 
  risk: string;
  datedeb: Date;
  datefin: Date; 
  min: number; 
  max: number; 
  sipminimum: any;
  sipmaximum: any; 
  
  TIT: Tit[] = [];

  constructor(
    private service: EditPurchasableSecuritiesService,
    private activatedRoute: ActivatedRoute,
    private location: Location,
    private router: Router,
    private decimalPipe: DecimalPipe,

    ) { }
  
    ngOnInit(): void {
      let svm: string | null;
      svm = this.activatedRoute.snapshot.paramMap.get('svm');
      if (!svm) {
        this.goBack();
        return;
      } 
      this.svm = svm;
      this.editPurchasableSecuritiesManagement(this.svm);
      this.datedeb = new Date();
      
    }

  ngOnDestroy(): void {
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }

  editPurchasableSecuritiesManagement(svm: string): void {
    this.service.editPurchasableSecuritiesManagement(this.svm).pipe(
      takeUntil(this.unsubscribe$)
    ).subscribe(res => {
      if (res.RETURNCODE === ApiResponseCodeEnum.Ok) {
     
        this.TIT = res.TIT;
        this.risk = res.TIT[0].AANBOD.RISK;
        this.datedeb = new Date();
        this.datefin = new Date(res.TIT[0].AANBOD.DATEVALID_FIN);
        this.min = res.TIT[0].AANBOD.QTTE_MIN;
        this.max = res.TIT[0].AANBOD.QTTE_MAX;
        this.sipminimum = this.decimalPipe.transform(res.TIT[0].AANBOD.SIPMINIMUM, '1.2-2'); 
        this.sipmaximum = this.decimalPipe.transform(res.TIT[0].AANBOD.SIPMAXIMUM, '1.2-2')
      }
    });
  }

  goBack(): void {
    this.location.back();
  }

  updatePurchasableSecuritiesManagement(): void {
    this.service.updatePurchasableSecuritiesManagement(this.svm, this.risk, this.datedeb, this.datefin, this.min, this.max,
      this.sipminimum, this.sipmaximum).pipe(
      takeUntil(this.unsubscribe$)
    ).subscribe(res => {
      if (res.RETURNCODE === ApiResponseCodeEnum.Ok) {
        this.router.navigateByUrl('/', { skipLocationChange: true }).then(() => {
          this.router.navigate(['functional-management/list-purchasable-securities']);   
        }); 
      }
    });
  }

  onInputChange(event: any, field: 'sipminimum' | 'sipmaximum'): void {
    // Récupérer la valeur entrée
    let value = event.target.value;
  
    // Conserver uniquement les chiffres et la virgule décimale
    value = value.replace(/[^0-9,.]/g, '');  // Supprimer tout sauf chiffres, point et virgule
  
    // Si un séparateur décimal est utilisé, ne garder que le premier (pas de multiples virgules ou points)
    const parts = value.split(/[,.]/); // Diviser en utilisant point ou virgule
    if (parts.length > 2) {
      value = parts[0] + '.' + parts.slice(1).join(''); // Conserver uniquement le premier séparateur
    }
  
    // Remplacer la virgule par un point (si nécessaire)
    value = value.replace(',', '.'); // Utiliser un point comme séparateur décimal
  
    // Convertir la valeur en nombre
    const parsedValue = value ? parseFloat(value) : 0;
  
    // Mettre à jour la variable en fonction du champ
    if (field === 'sipmaximum') {
      this.sipmaximum = parsedValue;
    } else if (field === 'sipminimum') {
      this.sipminimum = parsedValue;
    }
  }
  
  
}

template

<tr>
   <th>SIP minimum</th>
   <td>
      <input id="sipminimum" name="sipminimum" type="text" class="form-control" [(ngModel)]="sipminimum" [value]="sipminimum | number:'1.2-2'" (input)="onInputChange($event, 'sipminimum')" style="width: 70%" required appCommaToDot />
   </td>
</tr>
<tr>
   <th>SIP maximum</th>
   <td>
      <input id="sipmaximum" name="sipmaximum" type="text" class="form-control" [(ngModel)]="sipmaximum" [value]="sipmaximum | number:'1.2-2'" (input)="onInputChange($event, 'sipmaximum')" style="width: 70%" required appCommaToDot />
   </td>
</tr>

Thank you for your help.

Angular signals: how to update an item within an array which is the property of an object?

Perhaps I’m trying to use too-complex signals, let me know if what I am trying to achieve is just not a good use-case for Angular’s Signals and I guess I’ll try a different approach, but I feel like this should be do-able!

I have a service which is managing the state of an order – the order class contains some properties, one of those properties is an array of OrderItems.

I have created a signal for the Order PackingOrder = signal<order>(orderFromDB);
Which I can access just fine, but I am unable to figure out how to update an OrderItem within the order.

Given a Signal containing an Order object built using classes as below, how would one update, say, a specific OrderItem’s ‘packed’ property (given the OrderItem’s id)?

 export class Order {
  id: number; //USING THIS TO IDENTIFY THE ITEM...
  customer: string;
  orderItems: OrderItem[];
}

 export class OrderItem {
  id: number;
  produceName: string;
  unitQty: number;
  container: string;
  yield: number;
  packed: number; //<--HOW TO UPDATE THIS?
  complete: boolean;
}

I have searched for a solution but everything I have found has been targeting an array itself as the signal, or a simpler object, I’ve been unable to extend those answers into a working solution for this case, so here I am!

Cytoscape.js – Making Nodes present within container even if the node count and size are increasing dynamically

I am working to draw a flow chart with Cytoscape.js framework. I have n-number of nodes and edges. One node can have multiple children. The output should appear like a flow chart with connections.

Initially, I kept my container size as static. Based on node count increase, i am increasing the height of the container. And currently, few of my nodes are crossing the border of the container. So need a solution to avoid that problem. I am following breadthfirst layout.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
    <title>Cytoscape - Sample Data</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.0/cytoscape.min.js"></script>
    <style>
        #cy {
            width: 100%;
            height: 600px;
            /* position: absolute; */
            border: 1px solid black;
        }
    </style>
</head>
<body>
    <div id="cy">
    </div>

    <script>
        var elements = [
            {data:{id:"A", label:"A", shape: "diamond"}},
            {data:{id:"B", label:"B", shape: "diamond"}},
            {data:{id:"C", label:"C", shape: "diamond"}},
            {data:{id:"D", label:"D", shape: "diamond"}},
            {data:{id:"E", label:"E", shape: "diamond"}},
            {data:{id:"F", label:"F", shape: "diamond"}},
            {data:{id:"G", label:"G", shape: "diamond"}},
            {data:{id:"H", label:"H", shape: "diamond"}},
            {data:{id:"I", label:"I", shape: "diamond"}},
            {data:{id:"J", label:"J", shape: "diamond"}},
            {data:{id:"K", label:"K", shape: "diamond"}},
            {data:{id:"L", label:"L", shape: "diamond"}},
            {data: {source: "A", target: "B"}},
            {data: {source: "B", target: "C"}},
            {data: {source: "C", target: "D"}},
            {data: {source: "D", target: "E"}},
            {data: {source: "D", target: "F"}},
            {data: {source: "D", target: "G"}},
            {data: {source: "D", target: "H"}},
            {data: {source: "D", target: "I"}},
            {data: {source: "G", target: "J"}},
            {data: {source: "J", target: "K"}},
            {data: {source: "D", target: "L"}},
                ];

        var cy = cytoscape(
        {
            container: document.getElementById("cy"),
            elements: elements,
            style: [
                {
                    selector: "node",
                    style: {
                        "label": "data(label)",
                        "shape": "data(shape)",
                        'text-valign': 'center',
                        'text-halign': 'center',
                        "font-size": "25px",
                        "text-wrap": "wrap",
                        "color": "#000",
                        "width": "100px",
                        "height": "60px"
                    }
                },
                {
                    selector: "edge",
                    style: {
                        'width': "2px",
                        "height": "50px",
                        'line-color': '#000',
                        'target-arrow-shape': 'triangle-backcurve',
                        'target-arrow-color': '#000',
                        "curve-style": "bezier"
                    }
                }
            ],
            layout: {
                name: 'breadthfirst',
                directed: true,
                padding: 10,
                spacingFactor: 1.5, 
                fit: true, 
                avoidOverlap: true,
            },
            zoomingEnabled: false
        });

        function adjustContainerHeight(){
            var maxY = 0;
            var minY = Infinity; 

            cy.nodes().forEach(function(node) { 
                var nodePosition = node.position();
                var nodeY = nodePosition.y;
                maxY = Math.max(maxY, nodeY);
                minY = Math.min(minY, nodeY);
            });

            var newHeight = maxY - minY + 35;
            document.getElementById("cy").style.height = newHeight + "px";
        };

        adjustContainerHeight();
        cy.layout({name: 'breadthfirst', directed: true, padding: 10, spacingFactor: 1.5, fit: true, avoidOverlap: true, orientation: "vertical"}).run();

        cy.on("add", "node", function(){
            cy.layout({name: 'breadthfirst', directed: true, padding: 10, spacingFactor: 1.5, fit: true, avoidOverlap: true, orientation: "vertical"}).run();
            adjustContainerHeight();
        });

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

Extract value from iframe converting var content to text?

I’m trying to get the dollars value that is inside an iframe ($75.12). I can store the iframe doing this:

var frm = document.getElementsByTagName("iframe")[0]

but I cannot proceed doing something like

frm.contentWindow.document.getElementsByTagName("div")

since I get security error about cross origin frame.

Is there a way to store the content of variable frm in plain text? or what do you suggest?

The iframe looks like this:

<iframe class="transact-client-iframe transact-client-open" name="transact-client" src="https://examplesite.com">
'#document (https://examplesite.com)
<!DOCTYPE html>
<html lang="en-us">
    <head></head>
    <body class="transact__layout--flex">
        <div class="animated idx" style="display: none;"></div>
        <div id="ufst" class="vetyu-apptn">
            <div class="apptn">
            <div class="apptn_header"></div>
            <div class="apptn_content">
                <div class="py-values">
                    <div class="py-values_wallet">
                        <div class="py-values_balance">
                        <div id="vetyu6" class="help-popout vetyu-view"></div>
                        <div class="py-value">$75.12</div>
                        </div>
                    </div>
                    <div class="row align-center"></div>
                    <div class="py-values_ctas"></div>
                    <div class="py-values_preferences"></div>
                </div>
            </div>
            </div>
        </div>
        <form style="display: none"/></form>
    </body>
</html>
</iframe>

Pasting MathML equations generated by KaTeX into Word

When trying to paste Math equations from a KaTeX generated equation on the web to Microsoft Word 365, the whole equations gets correctly converted, but if there are Large Operators like Σ, word will show a placeholder next to it and then the indexed variable, instead of just showing the indexed variable inside the placeholder.

Example

What i get when copying a KaTeX equation from the web:

<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>N</mi></munderover><mrow><mo stretchy="false">(</mo><msup><mo stretchy="false">)</mo><mn>2</mn></msup><msub><mi>u</mi><mi>i</mi></msub></mrow><mo>=</mo><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>N</mi></munderover><mo stretchy="false">(</mo><msub><mi>Y</mi><mi>i</mi></msub><mo>−</mo><msub><mover accent="true"><mi>Y</mi><mo>^</mo></mover><mi>i</mi></msub><msup><mo stretchy="false">)</mo><mn>2</mn></msup><mo>=</mo><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>N</mi></munderover><mo stretchy="false">(</mo><msub><mi>Y</mi><mi>i</mi></msub><mo>−</mo><msub><mi>β</mi><mn>0</mn></msub><mo>−</mo><msub><mi>β</mi><mn>1</mn></msub><msub><mi>X</mi><mi>i</mi></msub><msup><mo stretchy="false">)</mo><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">sum_{i=1}^N (u_i)^2 = sum_{i=1}^N (Y_i - hat{Y}_i)^2 = sum_{i=1}^N (Y_i - beta_0 - beta_1 X_i)^2</annotation></semantics></math>

What i should have based on Word:

<mml:math xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"><mml:mrow><mml:munderover><mml:mo stretchy="true">∑</mml:mo><mml:mrow><mml:mi>i</mml:mi><mml:mo>=</mml:mo><mml:mn>1</mml:mn></mml:mrow><mml:mrow><mml:mi>N</mml:mi></mml:mrow></mml:munderover><mml:mrow><mml:mo>(</mml:mo><mml:msub><mml:mrow><mml:mi>u</mml:mi></mml:mrow><mml:mrow><mml:mi>i</mml:mi></mml:mrow></mml:msub><mml:msup><mml:mrow><mml:mo>)</mml:mo></mml:mrow><mml:mrow><mml:mn>2</mml:mn></mml:mrow></mml:msup></mml:mrow></mml:mrow><mml:mo>=</mml:mo><mml:mrow><mml:munderover><mml:mo stretchy="true">∑</mml:mo><mml:mrow><mml:mi>i</mml:mi><mml:mo>=</mml:mo><mml:mn>1</mml:mn></mml:mrow><mml:mrow><mml:mi>N</mml:mi></mml:mrow></mml:munderover><mml:mrow><mml:mo>(</mml:mo><mml:msub><mml:mrow><mml:mi>Y</mml:mi></mml:mrow><mml:mrow><mml:mi>i</mml:mi></mml:mrow></mml:msub><mml:mo>-</mml:mo><mml:msub><mml:mrow><mml:mover accent="true"><mml:mrow><mml:mi>Y</mml:mi></mml:mrow><mml:mo>^</mml:mo></mml:mover></mml:mrow><mml:mrow><mml:mi>i</mml:mi></mml:mrow></mml:msub><mml:msup><mml:mrow><mml:mo>)</mml:mo></mml:mrow><mml:mrow><mml:mn>2</mml:mn></mml:mrow></mml:msup></mml:mrow></mml:mrow><mml:mo>=</mml:mo><mml:mrow><mml:munderover><mml:mo stretchy="true">∑</mml:mo><mml:mrow><mml:mi>i</mml:mi><mml:mo>=</mml:mo><mml:mn>1</mml:mn></mml:mrow><mml:mrow><mml:mi>N</mml:mi></mml:mrow></mml:munderover><mml:mrow><mml:mo>(</mml:mo><mml:msub><mml:mrow><mml:mi>Y</mml:mi></mml:mrow><mml:mrow><mml:mi>i</mml:mi></mml:mrow></mml:msub><mml:mo>-</mml:mo><mml:msub><mml:mrow><mml:mi>β</mml:mi></mml:mrow><mml:mrow><mml:mn>0</mml:mn></mml:mrow></mml:msub><mml:mo>-</mml:mo><mml:msub><mml:mrow><mml:mi>β</mml:mi></mml:mrow><mml:mrow><mml:mn>1</mml:mn></mml:mrow></mml:msub><mml:msub><mml:mrow><mml:mi>X</mml:mi></mml:mrow><mml:mrow><mml:mi>i</mml:mi></mml:mrow></mml:msub><mml:msup><mml:mrow><mml:mo>)</mml:mo></mml:mrow><mml:mrow><mml:mn>2</mml:mn></mml:mrow></mml:msup></mml:mrow></mml:mrow></mml:math>

That said, i actually figured out that by just inserting a that comprehends the indexed variable, the issue is fixed. I don’t know how i could implement such a parsing with so many possible cases into a code that fixes the issue for me.

I tried to manually fix this by writing the element before and after each iterable variable, but i would like to write some code that does it automatically.

When do I need to call importNode/adoptNode?

On the MDN page for importNode, it says:

Before they can be inserted into the current document, nodes from external documents should either be:

cloned using document.importNode(); or

adopted using document.adoptNode().

It’s been a while since I’ve done anything involving multiple documents, and maybe I’m a little rusty, but I always thought the should in the snippet above was an indicator that you’d get an exception if you tried to add a foreign element without calling either function first.

I tried this in Edge’s console and there didn’t seem to be a problem moving nodes between documents.

let a = new Document();
let b = new Document();
b.appendChild(b.createElement("div"));
b.childNodes;
> NodeList [div]
b.firstChild.ownerDocument === b
> true
a.appendChild(b.firstChild);
a.childNodes;
> NodeList [div]
a.firstChild.ownerDocument === a
> true
b.childNodes;
> NodeList []

I seem to recall browsers being more hostile to this kind of manoeuvring in the past. Under what circumstances should I expect this to not work and give me an exception? Is it because there are no namespace differences? Are nodes auto-adopted? Have I made the Document objects the wrong way?

How to load sapui5 xml fragment in custom library that gets loaded from another app?

We have a custom library for controlls that we use across different sapui5 apps.
For js controls this works fine but now im trying to get it work with a xml fragment.

The library is deployed like an app and contains js files that extends sap/ui/base/Object and works fine.
We call it from other apps via

sap.ui.loader.config({
    paths: {
        'zfiorilibrary': sLibraryPath
    }
});

then we can access it from controller of the app by loading it as you load any other objects from sapui5 declaring it at the top in sap.ui.define()

now i tried the same with an xml file that is in the library and it wont load and gives me cors error in console.
this._oAttachmentsMangerDialog = sap.ui.xmlfragment("library-AttachmentsManager", "zfiorilibrary.fragments.AttachmentsManager", this);

jquery-dbg.js:9325 Access to XMLHttpRequest at 'https://ourserver/sap/bc/ui5_ui5/sap/zfiorilibrary/fragments/AttachmentsManager.fragment.xml' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

when i click the url the xml loads fine

we never have cors errors when loading the js files.
What can i do to load xml files from the library?

We are using sapui5 version 1.71.x (always the newest 1.71 available)

How do I get the cookies without having to pass them to API functions from server components?

I can get the cookies in server side components and pass them to API functions like this:

import { cookies } from 'next/headers';

const cookieStore = cookies();
const sessionId = cookieStore.get('SESSIONID.DEV')?.value;

const asset = await queryClient.fetchQuery({
  queryKey: ['asset', params.id],
  queryFn: () => fetchData(params.id, sessionId),
});

console.log('Fetched asset:', asset);

Then in api.ts, I have something like this (otherwise, the cookies won’t be sent in server side components, and I’ll get a 401 unauthorized error):

const api = axios.create({
  baseURL: getBaseUrl(),
  headers: {
    Accept: 'application/hal+json',
    'Content-Type': 'application/json',
  },
  withCredentials: true,
});
 
export const fetchData = async (id: string, sessionId: string) => {
  try {
    const response = await api.get(`/data/${id}`, {
      headers: {
        'Accept-Version': '0.24.0.0',
        Cookie: `SESSIONID.DEV=${sessionId}`,
      },
    });

    return response.data;
  } catch (error) {
    console.error('Error fetching current asset', error);
    throw error;
  }
};

But I don’t want to pass sessionId to every API function, so I tried getting the cookies in my api.ts file. However, I got this error:

Invariant: cookies() expects to have requestAsyncStorage, none available.

So it seems like I can only use Next.js’ cookies in server components. How can I solve this dilemma?

react -native doctor command failing

Getting error at Android SDK line

Error : SDK Versions Mismatching.

✖ Android SDK – Required for building and installing your app on Android

  • Versions found: 34.0.0, 35.0.0
  • Version supported: .b34.0.0
PS F:StReactNativeProjectsreactexpo1> npx react-native doctor
⠋ Running diagnostics...(node:9244) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
⠹ Running diagnostics...* daemon not running; starting now at tcp:5037
* daemon started successfully
Common
 ✓ Node.js - Required to execute JavaScript code
 ✓ npm - Required to install NPM dependencies
 ● Metro - Metro Bundler is not running

Android
 ✓ Adb - Required to verify if the android device is attached correctly
 ✓ JDK - Required to compile Java code
 ✓ Android Studio - Required for building and installing your app on Android
 ✓ ANDROID_HOME - Environment variable that points to your Android SDK installation
 ✓ Gradlew - Build tool required for Android builds
 ✖ Android SDK - Required for building and installing your app on Android
   - Versions found: 34.0.0, 35.0.0
   - Version supported: .b34.0.0

Errors:   1
Warnings: 1

Usage
 › Press f to try to fix issues.
 › Press e to try to fix errors.
 › Press w to try to fix warnings.
 › Press Enter to exit.

When i will run, it should work properly.

npx react-native doctor

Pressing Back button still calls ondisconnect – SignalR

I have 2 pages

ReviewPage.cshtml => SubmitAnswer.cshtml

The SubmitAnswer only has the signalr.js and will reconnect on disconnect

But when I navigate back to ReviewPage, the SubmitAnswer page will disconnect and try to reconnect while loading the ReviewPage and causes error due to it failed to get a clientid/sessionid on the ReviewPage

The problem is, this doesn’t happen on my local machine and our qa, it only happens on prod. In my local machine and qa, it doesn’t disconnect and try to reconnect before loading ReviewPage, but only on prod.

Is it a server configuration or a bug in signalr?

Cannot Implicity convert ‘array’ to ‘string’…sending data from controller to chart js

need help with my code
So the problem is i tried to pass array from the controller to my page that contain a bar chart..But the chart cannot be displayed because it doesnt correctly received the array i passed from the controller.

At this Line on main.php:
var data = {$data};
there is yellow line says “cannot implicity convert array from strings”

ChartController.php

{
    public function actionIndex()
    {

        $commonKpiTotalScoreQ1 = $this->getQuartPerformanceData(1);
        $commonKpiTotalScoreQ2 = $this->getQuartPerformanceData(2);
        $commonKpiTotalScoreQ3 = $this->getQuartPerformanceData(3);
        $commonKpiTotalScoreQ4 = $this->getQuartPerformanceData(4);

        $data = [
            'Q1' => $commonKpiTotalScoreQ1,
            'Q2' => $commonKpiTotalScoreQ2,
            'Q3' => $commonKpiTotalScoreQ3,
            'Q4' => $commonKpiTotalScoreQ4,
        ];

        return $this->render('index', [

            'data' => json_encode($data),
        ]);
    }

main.php

<?php
$this->registerJs(<<<JS

        var data = {$data};
        // Process the fetched data
        var kpiScores = [data.Q1, data.Q2, data.Q3, data.Q4];

        var ctx = document.getElementById('myChart').getContext('2d');
        var myChart = new Chart(ctx, {
            type: 'bar',
            data: {
                labels: ['1st Quarter', '2nd Quarter', '3rd Quarter', '4th Quarter'],
                datasets: [{
                    label: 'Performance Score',
                    data: kpiScores,
                    backgroundColor: [
                        'rgba(255, 99, 132, 0.2)',
                        'rgba(54, 162, 235, 0.2)',
                        'rgba(255, 206, 86, 0.2)',
                        'rgba(75, 192, 192, 0.2)'
                    ],
                    borderColor: [
                        'rgba(255, 99, 132, 1)',
                        'rgba(54, 162, 235, 1)',
                        'rgba(255, 206, 86, 1)',
                        'rgba(75, 192, 192, 1)'
                    ],
                    borderWidth: 1
                }]
            },
            options: {
                scales: {
                    y: {
                        beginAtZero: true,
                        max: 100
                    }
                }
            }
        });
JS
);
?>

Mapbox GL JS – fitBounds with bearing and/or pitch sets bounds for North aligned, zero pitch map. How to set bounds for rotated map?

I have a JS class to add maps with routes to my page (mapbox-gl-js v3.8.0).

Once the route has loaded, I’m using fitBounds to adjust the map to fill the available space with the route.

This all works fine until I apply a bearing and/or pitch. What seems to happen is that the map is zoomed to fill with the route as if bearing & pitch are both zero, then the bearing & pitch are applied. This has the effect of making the route either too small or too big (depending on orientation etc).

I’ve tried making an array of my points transformed by the bearing and creating a bounds rectangle from that which should in theory work, but it just results in the same end where the size/zoom is optimised for the north aligned view before applying the rotation.

Does anyone have any insight into how I can fill the map container with my rotated route?

The relevant class methods for getting and fitting the route are:

    setView = (bounds, duration = 0) => {
        // bounds should be array of arrays in format [[min_lng, min_lat],[max_lng, max_lat]]
        // duration is animation length in milliseconds
        this.map.fitBounds(bounds, {
            padding: {
                top: this.map_settings.padding.top,
                right: this.map_settings.padding.right,
                bottom: this.map_settings.padding.bottom,
                left: this.map_settings.padding.left,
            },
            pitch: this.map_settings.pitch,
            bearing: this.map_settings.bearing,
            duration: duration
        });
    }

    drawRoute = async () => {
        // build the gps points query string
        const points = this.map_settings.waypoints.map((coord) => [coord.longitude, coord.latitude].join());
        const gps_list = points.join(";");
        const query = await fetch(
            `https://api.mapbox.com/directions/v5/mapbox/${this.map_settings.route_type}/${gps_list}?steps=false&geometries=geojson&access_token=${mapboxgl.accessToken}`,
            { method: "GET" }
        );
        // return if api call not successful
        if (!query.ok) {
            console.warn("Map Block: Error determining route");
            return
        }

        const json = await query.json();
        const data = json.routes[0];
        const route = data.geometry.coordinates;
        const geojson = {
            type: "Feature",
            properties: {},
            geometry: {
                type: "LineString",
                coordinates: route,
            },
        };
        this.map.addLayer({
            id: `route-${this.map_settings.uid}`,
            type: "line",
            source: {
                type: "geojson",
                data: geojson,
            },
            layout: {
                "line-join": "round",
                "line-cap": "round",
            },
            paint: {
                "line-color": "#3887be",
                "line-width": 5,
                "line-opacity": 0.75,
            },
        });

        // set map bounds to fit route
        const bounds = new mapboxgl.LngLatBounds(route[0], route[0]);
        for (const coord of route) {
            bounds.extend(coord);
        }
        this.setView(bounds, 1000);
    }

I’ve tried this from the console with no luck, it was my last iteration of trying to get this to work:

fitRotatedRoute = (routeCoordinates, mapBearing) => {
    // Step 1: Rotate the route coordinates by the negative of the map's bearing
    const radians = (mapBearing * Math.PI) / 180; // Convert map bearing to radians

    // Function to rotate a point by the given angle
    const rotatePoint = ([lng, lat], center, radians) => {
        const dx = lng - center.lng;
        const dy = lat - center.lat;
        return [
            center.lng + dx * Math.cos(radians) - dy * Math.sin(radians),
            center.lat + dx * Math.sin(radians) + dy * Math.cos(radians),
        ];
    };

    // Step 2: Find the centroid of the route (average of coordinates)
    const centroid = routeCoordinates.reduce(
        (acc, [lng, lat]) => ({
            lng: acc.lng + lng / routeCoordinates.length,
            lat: acc.lat + lat / routeCoordinates.length,
        }),
        { lng: 0, lat: 0 }
    );

    // Step 3: Rotate each coordinate by the negative of the map's bearing
    const rotatedPoints = routeCoordinates.map((coord) =>
        rotatePoint(coord, centroid, -radians)
    );

    // Step 4: Calculate the axis-aligned bounding box (AABB) of the rotated coordinates
    const minLng = Math.min(...rotatedPoints.map(([lng]) => lng));
    const maxLng = Math.max(...rotatedPoints.map(([lng]) => lng));
    const minLat = Math.min(...rotatedPoints.map(([_, lat]) => lat));
    const maxLat = Math.max(...rotatedPoints.map(([_, lat]) => lat));

    // Step 5: Fit the bounds on the map using the calculated AABB
    testMap.fitBounds(
        [
            [minLng, minLat], // Southwest corner
            [maxLng, maxLat], // Northeast corner
        ],
        {
            padding: {
                top: mapSettings.padding.top,
                right: mapSettings.padding.right,
                bottom: mapSettings.padding.bottom,
                left: mapSettings.padding.left,
            },
            pitch: mapSettings.pitch,
            bearing: mapBearing, // Apply map bearing (rotation)
            duration: 1000, // Animation duration
        }
    );
}

With pitch and bearing both 0, all works as it should:
pitch and bearing both 0

With bearing -60 & using the class getRoute() method:
pitch zero, bearing -60, using class method

It’s not only not fitted the route, it’s at an even lower zoom level than bearing=0.

With bearing -60 and using the test fitRotatedRoute() function:
pitch zero, bearing -60, using test method

Slightly better zoom level but still a long way off.

If anyone has any insight into how to do this properly, it’d be great to know. MapBox docs only seem to deal with bearing/pitch zero examples.

Google Lens search issues,- Google Images works fine

I was using the following code from a Chrome extension and it was working fine up until a few days ago, meaning Google must’ve introduced a change of some sort. I’ve been trying to fogure this out without success …

I have the following code, can be executed from a background script:

fetch("data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7")
    .then(function(response) { return response.blob(); })
    .then(function(blob) {
        var form = new FormData();
        form.append("encoded_image", blob, "blob");
        form.append("sbisrc", navigator.userAgent);

        fetch("https://www.google.com/searchbyimage/upload", { method: "POST", body: form })
            .then(function(response) {
                console.log(response.url); // opening the URL loads results
            })
            .catch(function(error) {});
    })
    .catch(function(error) {});

The following works fine (Google Images) however once the URL is changed
from:
“https://www.google.com/searchbyimage/upload”
to:
“https://lens.google.com/v3/upload”

We see that it fails and I’m trying to figure out what’s going on …

I might have to change the code and upload the images temporarily to let’s say imgur before sending to Google, but would prefer to get it working directly like it always did