forked from OpenWF/SpaceNinjaServer
		
	chore(webui): keep config in sync with multiple tabs (#2325)
Adding "wsid" to uniquely identify a given tab (by the websocket connection) so we can avoid needless refreshing on the same tab. Closes #2316 Reviewed-on: OpenWF/SpaceNinjaServer#2325 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									4895b4630b
								
							
						
					
					
						commit
						abb5b8880f
					
				@ -2,6 +2,7 @@ import { RequestHandler } from "express";
 | 
				
			|||||||
import { config } from "@/src/services/configService";
 | 
					import { config } from "@/src/services/configService";
 | 
				
			||||||
import { getAccountForRequest, isAdministrator } from "@/src/services/loginService";
 | 
					import { getAccountForRequest, isAdministrator } from "@/src/services/loginService";
 | 
				
			||||||
import { saveConfig } from "@/src/services/configWatcherService";
 | 
					import { saveConfig } from "@/src/services/configWatcherService";
 | 
				
			||||||
 | 
					import { sendWsBroadcastExcept } from "@/src/services/webService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getConfigController: RequestHandler = async (req, res) => {
 | 
					export const getConfigController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const account = await getAccountForRequest(req);
 | 
					    const account = await getAccountForRequest(req);
 | 
				
			||||||
@ -24,6 +25,7 @@ export const setConfigController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
            const [obj, idx] = configIdToIndexable(id);
 | 
					            const [obj, idx] = configIdToIndexable(id);
 | 
				
			||||||
            obj[idx] = value;
 | 
					            obj[idx] = value;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        sendWsBroadcastExcept(parseInt(String(req.query.wsid)), { config_reloaded: true });
 | 
				
			||||||
        await saveConfig();
 | 
					        await saveConfig();
 | 
				
			||||||
        res.end();
 | 
					        res.end();
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
 | 
				
			|||||||
@ -136,7 +136,10 @@ export const stopWebServer = async (): Promise<void> => {
 | 
				
			|||||||
    await Promise.all(promises);
 | 
					    await Promise.all(promises);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let lastWsid: number = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface IWsCustomData extends ws {
 | 
					interface IWsCustomData extends ws {
 | 
				
			||||||
 | 
					    id?: number;
 | 
				
			||||||
    accountId?: string;
 | 
					    accountId?: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -150,6 +153,7 @@ interface IWsMsgFromClient {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface IWsMsgToClient {
 | 
					interface IWsMsgToClient {
 | 
				
			||||||
 | 
					    //wsid?: number;
 | 
				
			||||||
    reload?: boolean;
 | 
					    reload?: boolean;
 | 
				
			||||||
    ports?: {
 | 
					    ports?: {
 | 
				
			||||||
        http: number | undefined;
 | 
					        http: number | undefined;
 | 
				
			||||||
@ -174,6 +178,10 @@ const wsOnConnect = (ws: ws, req: http.IncomingMessage): void => {
 | 
				
			|||||||
        ws.close();
 | 
					        ws.close();
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (ws as IWsCustomData).id = ++lastWsid;
 | 
				
			||||||
 | 
					    ws.send(JSON.stringify({ wsid: lastWsid }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // eslint-disable-next-line @typescript-eslint/no-misused-promises
 | 
					    // eslint-disable-next-line @typescript-eslint/no-misused-promises
 | 
				
			||||||
    ws.on("message", async msg => {
 | 
					    ws.on("message", async msg => {
 | 
				
			||||||
        const data = JSON.parse(String(msg)) as IWsMsgFromClient;
 | 
					        const data = JSON.parse(String(msg)) as IWsMsgFromClient;
 | 
				
			||||||
@ -268,3 +276,21 @@ export const sendWsBroadcastTo = (accountId: string, data: IWsMsgToClient): void
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const sendWsBroadcastExcept = (wsid: number | undefined, data: IWsMsgToClient): void => {
 | 
				
			||||||
 | 
					    const msg = JSON.stringify(data);
 | 
				
			||||||
 | 
					    if (wsServer) {
 | 
				
			||||||
 | 
					        for (const client of wsServer.clients) {
 | 
				
			||||||
 | 
					            if ((client as IWsCustomData).id != wsid) {
 | 
				
			||||||
 | 
					                client.send(msg);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (wssServer) {
 | 
				
			||||||
 | 
					        for (const client of wssServer.clients) {
 | 
				
			||||||
 | 
					            if ((client as IWsCustomData).id != wsid) {
 | 
				
			||||||
 | 
					                client.send(msg);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
let auth_pending = false,
 | 
					let auth_pending = false,
 | 
				
			||||||
    did_initial_auth = false,
 | 
					    did_initial_auth = false,
 | 
				
			||||||
    ws_is_open = false;
 | 
					    ws_is_open = false,
 | 
				
			||||||
 | 
					    wsid = 0;
 | 
				
			||||||
const sendAuth = isRegister => {
 | 
					const sendAuth = isRegister => {
 | 
				
			||||||
    if (ws_is_open && localStorage.getItem("email") && localStorage.getItem("password")) {
 | 
					    if (ws_is_open && localStorage.getItem("email") && localStorage.getItem("password")) {
 | 
				
			||||||
        auth_pending = true;
 | 
					        auth_pending = true;
 | 
				
			||||||
@ -34,6 +35,9 @@ function openWebSocket() {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
    window.ws.onmessage = e => {
 | 
					    window.ws.onmessage = e => {
 | 
				
			||||||
        const msg = JSON.parse(e.data);
 | 
					        const msg = JSON.parse(e.data);
 | 
				
			||||||
 | 
					        if ("wsid" in msg) {
 | 
				
			||||||
 | 
					            wsid = msg.wsid;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        if ("reload" in msg) {
 | 
					        if ("reload" in msg) {
 | 
				
			||||||
            setTimeout(() => {
 | 
					            setTimeout(() => {
 | 
				
			||||||
                getWebSocket().then(() => {
 | 
					                getWebSocket().then(() => {
 | 
				
			||||||
@ -1858,7 +1862,7 @@ for (const id of uiConfigs) {
 | 
				
			|||||||
                value = parseInt(value);
 | 
					                value = parseInt(value);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            $.post({
 | 
					            $.post({
 | 
				
			||||||
                url: "/custom/setConfig?" + window.authz,
 | 
					                url: "/custom/setConfig?" + window.authz + "&wsid=" + wsid,
 | 
				
			||||||
                contentType: "application/json",
 | 
					                contentType: "application/json",
 | 
				
			||||||
                data: JSON.stringify({ [id]: value })
 | 
					                data: JSON.stringify({ [id]: value })
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
@ -1866,7 +1870,7 @@ for (const id of uiConfigs) {
 | 
				
			|||||||
    } else if (elm.type == "checkbox") {
 | 
					    } else if (elm.type == "checkbox") {
 | 
				
			||||||
        elm.onchange = function () {
 | 
					        elm.onchange = function () {
 | 
				
			||||||
            $.post({
 | 
					            $.post({
 | 
				
			||||||
                url: "/custom/setConfig?" + window.authz,
 | 
					                url: "/custom/setConfig?" + window.authz + "&wsid=" + wsid,
 | 
				
			||||||
                contentType: "application/json",
 | 
					                contentType: "application/json",
 | 
				
			||||||
                data: JSON.stringify({ [id]: this.checked })
 | 
					                data: JSON.stringify({ [id]: this.checked })
 | 
				
			||||||
            }).then(() => {
 | 
					            }).then(() => {
 | 
				
			||||||
@ -1881,7 +1885,7 @@ for (const id of uiConfigs) {
 | 
				
			|||||||
function doSaveConfig(id) {
 | 
					function doSaveConfig(id) {
 | 
				
			||||||
    const elm = document.getElementById(id);
 | 
					    const elm = document.getElementById(id);
 | 
				
			||||||
    $.post({
 | 
					    $.post({
 | 
				
			||||||
        url: "/custom/setConfig?" + window.authz,
 | 
					        url: "/custom/setConfig?" + window.authz + "&wsid=" + wsid,
 | 
				
			||||||
        contentType: "application/json",
 | 
					        contentType: "application/json",
 | 
				
			||||||
        data: JSON.stringify({ [id]: parseInt(elm.value) })
 | 
					        data: JSON.stringify({ [id]: parseInt(elm.value) })
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user