From c3cc8f153550eafb34e0ff5970f0040af9b6c577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fred=20Lef=C3=A9v=C3=A8re-Laoide?= Date: Wed, 2 Oct 2024 14:16:11 +0200 Subject: [PATCH 1/3] Stack broadcasts so that not one is lost resolves #1608 --- frontend/taipy-gui/package-lock.json | 138 ++++++-------- frontend/taipy-gui/package.json | 4 +- frontend/taipy-gui/packaging/taipy-gui.d.ts | 20 ++ frontend/taipy-gui/src/components/Router.tsx | 4 +- .../src/context/taipyReducers.spec.ts | 8 +- .../taipy-gui/src/context/taipyReducers.ts | 85 +++++++-- frontend/taipy-gui/src/context/wsUtils.ts | 7 +- frontend/taipy-gui/src/extensions/exports.ts | 4 + frontend/taipy/package-lock.json | 153 +++++++-------- frontend/taipy/package.json | 3 +- frontend/taipy/src/CoreSelector.tsx | 33 ++-- frontend/taipy/src/DataNodeChart.tsx | 6 +- frontend/taipy/src/DataNodeTable.tsx | 14 +- frontend/taipy/src/DataNodeViewer.tsx | 174 +++++++++--------- frontend/taipy/src/JobSelector.tsx | 34 ++-- frontend/taipy/src/JobViewer.tsx | 36 ++-- frontend/taipy/src/NodeSelector.tsx | 12 +- frontend/taipy/src/PropertiesEditor.tsx | 13 +- frontend/taipy/src/ScenarioDag.tsx | 58 +++--- frontend/taipy/src/ScenarioSelector.tsx | 16 +- frontend/taipy/src/ScenarioViewer.tsx | 149 ++++++++------- frontend/taipy/src/utils.ts | 21 ++- taipy/gui/gui.py | 2 +- taipy/gui/types.py | 1 + 24 files changed, 546 insertions(+), 449 deletions(-) diff --git a/frontend/taipy-gui/package-lock.json b/frontend/taipy-gui/package-lock.json index 8cfbe53c1f..c9039a4678 100644 --- a/frontend/taipy-gui/package-lock.json +++ b/frontend/taipy-gui/package-lock.json @@ -34,8 +34,7 @@ "react-window": "^1.8.6", "react-window-infinite-loader": "^1.0.7", "socket.io-client": "^4.3.2", - "sprintf-js": "^1.1.2", - "uuid": "^10.0.0" + "sprintf-js": "^1.1.2" }, "devDependencies": { "@testing-library/jest-dom": "^6.1.3", @@ -52,7 +51,6 @@ "@types/react-window": "^1.8.5", "@types/react-window-infinite-loader": "^1.0.5", "@types/sprintf-js": "^1.1.2", - "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^8.5.0", "@typescript-eslint/parser": "^8.5.0", "add-asset-html-webpack-plugin": "^6.0.0", @@ -3243,12 +3241,6 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==" }, - "node_modules/@types/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", - "dev": true - }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -3265,16 +3257,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz", - "integrity": "sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", + "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/type-utils": "8.7.0", - "@typescript-eslint/utils": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/type-utils": "8.8.0", + "@typescript-eslint/utils": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -3298,15 +3290,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.7.0.tgz", - "integrity": "sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", + "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4" }, "engines": { @@ -3326,13 +3318,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz", - "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", + "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0" + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3343,13 +3335,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz", - "integrity": "sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", + "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.7.0", - "@typescript-eslint/utils": "8.7.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/utils": "8.8.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -3367,9 +3359,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz", - "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", + "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3380,13 +3372,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz", - "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", + "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3408,15 +3400,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz", - "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", + "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0" + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3430,12 +3422,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz", - "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", + "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/types": "8.8.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -4541,9 +4533,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001664", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz", - "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==", + "version": "1.0.30001666", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001666.tgz", + "integrity": "sha512-gD14ICmoV5ZZM1OdzPWmpx+q4GyefaK06zi8hmfHV5xe4/2nOQX3+Dw5o+fSqOws2xVwL9j+anOPFwHzdEdV4g==", "funding": [ { "type": "opencollective", @@ -5713,11 +5705,11 @@ } }, "node_modules/date-fns-tz": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-3.1.3.tgz", - "integrity": "sha512-ZfbMu+nbzW0mEzC8VZrLiSWvUIaI3aRHeq33mTe7Y38UctKukgqPR4nTDwcwS4d64Gf8GghnVsroBuMY3eiTeA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-3.2.0.tgz", + "integrity": "sha512-sg8HqoTEulcbbbVXeg84u5UnlsQa8GS5QXMqjjYIhS4abEVVKIUwe0/l/UhrZdKaL/W5eWZNlbTeEIiOXTcsBQ==", "peerDependencies": { - "date-fns": "^3.0.0" + "date-fns": "^3.0.0 || ^4.0.0" } }, "node_modules/debug": { @@ -6115,9 +6107,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.29", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz", - "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==" + "version": "1.5.31", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.31.tgz", + "integrity": "sha512-QcDoBbQeYt0+3CWcK/rEbuHvwpbT/8SV9T3OSgs6cX1FlcUAkgrkqbg9zLnDrMM/rLamzQwal4LYFCiWk861Tg==" }, "node_modules/element-size": { "version": "1.1.1", @@ -6569,9 +6561,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.0.tgz", - "integrity": "sha512-IHBePmfWH5lKhJnJ7WB1V+v/GolbB0rjS8XYVCSQCZKaQCAUhMoVoOEn1Ef8Z8Wf0a7l8KTJvuZg5/e4qrZ6nA==", + "version": "7.37.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.1.tgz", + "integrity": "sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==", "dev": true, "dependencies": { "array-includes": "^3.1.8", @@ -15732,9 +15724,9 @@ } }, "node_modules/typedoc-plugin-markdown": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.2.8.tgz", - "integrity": "sha512-1EDsc66jaCjZtxdYy+Rl0KDU1WY/iyuCOOPaeFzcYFZ81FNXV8CmgUDOHri20WGmYnkEM5nQ+ooxj1vyuQo0Lg==", + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.2.9.tgz", + "integrity": "sha512-Wqmx+7ezKFgtTklEq/iUhQ5uFeBDhAT6wiS2na9cFLidIpl9jpDHJy/COYh8jUZXgIRIZVQ/bPNjyrnPFoDwzg==", "dev": true, "engines": { "node": ">= 18" @@ -16010,18 +16002,6 @@ "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", "dev": true }, - "node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", diff --git a/frontend/taipy-gui/package.json b/frontend/taipy-gui/package.json index d878e7019a..d345ebd91d 100644 --- a/frontend/taipy-gui/package.json +++ b/frontend/taipy-gui/package.json @@ -29,8 +29,7 @@ "react-window": "^1.8.6", "react-window-infinite-loader": "^1.0.7", "socket.io-client": "^4.3.2", - "sprintf-js": "^1.1.2", - "uuid": "^10.0.0" + "sprintf-js": "^1.1.2" }, "overrides": { "react": "$react", @@ -89,7 +88,6 @@ "@types/react-window": "^1.8.5", "@types/react-window-infinite-loader": "^1.0.5", "@types/sprintf-js": "^1.1.2", - "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^8.5.0", "@typescript-eslint/parser": "^8.5.0", "add-asset-html-webpack-plugin": "^6.0.0", diff --git a/frontend/taipy-gui/packaging/taipy-gui.d.ts b/frontend/taipy-gui/packaging/taipy-gui.d.ts index 005e9c48cb..1f91befc50 100644 --- a/frontend/taipy-gui/packaging/taipy-gui.d.ts +++ b/frontend/taipy-gui/packaging/taipy-gui.d.ts @@ -323,6 +323,26 @@ export declare const createRequestUpdateAction: ( forceRefresh?: boolean, stateContext?: Record ) => Action; + +/** + * Broadcast stack definition. + */ +export interface BroadcastDesc { + /** Name of the broadcast. */ + name: string; + /** Broadcast stack */ + stack: Array; +} + +/** + * Create an *un broadcast* `Action` that will be used to update local state. + * + * This action will remove a value from a broadcasted stacked variable identified by name. + * @param name - The name of the variable identifying the broadcast. + * @param values - The values to remove. + * @returns The action fed to the reducer. + */ +export declare const createUnBroadcastAction: (name: string, ...values: Array) => Action; /** * A column description as received by the backend. */ diff --git a/frontend/taipy-gui/src/components/Router.tsx b/frontend/taipy-gui/src/components/Router.tsx index d3b3a1f788..7e12d0c42b 100644 --- a/frontend/taipy-gui/src/components/Router.tsx +++ b/frontend/taipy-gui/src/components/Router.tsx @@ -30,7 +30,7 @@ import { createSetLocationsAction, initializeWebSocket, INITIAL_STATE, - retreiveBlockUi, + retrieveBlockUi, taipyInitialize, taipyReducer, } from "../context/taipyReducers"; @@ -79,7 +79,7 @@ const Router = () => { .then((result) => { dispatch(createSetLocationsAction(result.data.locations)); setRoutes(result.data.locations); - result.data.blockUI && dispatch(createBlockAction(retreiveBlockUi())); + result.data.blockUI && dispatch(createBlockAction(retrieveBlockUi())); }) .catch((error) => { // Fallback router if there is any error diff --git a/frontend/taipy-gui/src/context/taipyReducers.spec.ts b/frontend/taipy-gui/src/context/taipyReducers.spec.ts index 176db6d18f..5c2897f107 100644 --- a/frontend/taipy-gui/src/context/taipyReducers.spec.ts +++ b/frontend/taipy-gui/src/context/taipyReducers.spec.ts @@ -38,7 +38,7 @@ import { messageToAction, NamePayload, NavigateMessage, - retreiveBlockUi, + retrieveBlockUi, storeBlockUi, TaipyBaseAction, taipyReducer, @@ -777,19 +777,19 @@ describe("retreiveBlockUi function", () => { it("should retrieve block message from localStorage", () => { const mockBlockMessage = { action: "testAction", noCancel: false, close: false, message: "testMessage" }; Storage.prototype.getItem = jest.fn(() => JSON.stringify(mockBlockMessage)); - const result = retreiveBlockUi(); + const result = retrieveBlockUi(); expect(result).toEqual(mockBlockMessage); }); it("should return an empty object if localStorage is empty", () => { Storage.prototype.getItem = jest.fn(() => null); - const result = retreiveBlockUi(); + const result = retrieveBlockUi(); expect(result).toEqual({}); }); it("should return an empty object if localStorage contains invalid JSON", () => { Storage.prototype.getItem = jest.fn(() => "{ invalid json"); - const result = retreiveBlockUi(); + const result = retrieveBlockUi(); expect(result).toEqual({}); }); }); diff --git a/frontend/taipy-gui/src/context/taipyReducers.ts b/frontend/taipy-gui/src/context/taipyReducers.ts index db360b13aa..fa266831dc 100644 --- a/frontend/taipy-gui/src/context/taipyReducers.ts +++ b/frontend/taipy-gui/src/context/taipyReducers.ts @@ -46,6 +46,8 @@ export enum Types { DownloadFile = "DOWNLOAD_FILE", Partial = "PARTIAL", Acknowledgement = "ACKNOWLEDGEMENT", + Broadcast = "BROADCAST", + UnBroadcast = "UNBROADCAST", } /** @@ -156,6 +158,16 @@ export interface FormatConfig { number: string; } +/** + * Broadcast stack definition. + */ +export interface BroadcastDesc { + /** Name of the broadcast. */ + name: string; + /** Broadcast stack */ + stack: Array; +} + const getUserTheme = (mode: PaletteMode) => { const tkTheme = (window.taipyConfig?.stylekit && stylekitTheme) || {}; const tkModeTheme = (window.taipyConfig?.stylekit && stylekitModeThemes[mode]) || {}; @@ -173,7 +185,7 @@ const getUserTheme = (mode: PaletteMode) => { }, }, }, - }), + }) ); }; @@ -218,7 +230,7 @@ export const messageToAction = (message: WsMessage) => { (message as unknown as NavigateMessage).to, (message as unknown as NavigateMessage).params, (message as unknown as NavigateMessage).tab, - (message as unknown as NavigateMessage).force, + (message as unknown as NavigateMessage).force ); } else if (message.type === "ID") { return createIdAction((message as unknown as IdMessage).id); @@ -230,6 +242,8 @@ export const messageToAction = (message: WsMessage) => { return createAckAction((message as unknown as IdMessage).id); } else if (message.type === "FV") { changeFavicon((message.payload as Record)?.value); + } else if (message.type == "BC") { + return createBroadcastAction(message as unknown as NamePayload); } } return {} as TaipyBaseAction; @@ -300,7 +314,7 @@ export const storeBlockUi = (block?: BlockMessage) => () => { } }; -export const retreiveBlockUi = (): BlockMessage => { +export const retrieveBlockUi = (): BlockMessage => { if (localStorage) { const val = localStorage.getItem("TaipyBlockUi"); if (val) { @@ -342,6 +356,30 @@ export const taipyReducer = (state: TaipyState, baseAction: TaipyBaseAction): Ta : newValue, }, }; + case Types.Broadcast: + return { + ...state, + data: { + ...state.data, + [action.name]: { + name: action.name, + stack: [...((state.data[action.name] || {stack: []}) as BroadcastDesc).stack , action.payload.value], + }, + }, + }; + case Types.UnBroadcast: + return { + ...state, + data: { + ...state.data, + [action.name]: { + name: action.name, + stack: ((state.data[action.name] || {stack: []}) as BroadcastDesc).stack.filter( + (v) => !(action.payload.value as Array).includes(v) + ), + }, + }, + }; case Types.SetLocations: return { ...state, locations: action.payload.value as Record }; case Types.SetAlert: @@ -463,7 +501,7 @@ export const taipyReducer = (state: TaipyState, baseAction: TaipyBaseAction): Ta action.payload, state.id, action.context, - action.propagate, + action.propagate ); break; case Types.Action: @@ -485,6 +523,25 @@ export const createUpdateAction = (payload: NamePayload): TaipyAction => ({ type: Types.Update, }); +export const createBroadcastAction = (payload: NamePayload): TaipyAction => ({ + ...payload, + type: Types.Broadcast, +}); + +/** + * Create an *un broadcast* `Action` that will be used to update local state. + * + * This action will remove a value from a broadcasted stacked variable identified by name. + * @param name - The name of the variable identifying the broadcast. + * @param values - The values to remove. + * @returns The action fed to the reducer. + */ +export const createUnBroadcastAction = (name: string, ...values: Array): TaipyAction => ({ + type: Types.UnBroadcast, + name, + payload: getPayload(values), +}); + export const createMultipleUpdateAction = (payload: NamePayload[]): TaipyMultipleAction => ({ type: Types.MultipleUpdate, payload: payload, @@ -513,7 +570,7 @@ export const createSendUpdateAction = ( context: string | undefined, onChange?: string, propagate = true, - relName?: string, + relName?: string ): TaipyAction => ({ type: Types.SendUpdate, name: name, @@ -566,7 +623,7 @@ export const createRequestChartUpdateAction = ( context: string | undefined, columns: string[], pageKey: string, - decimatorPayload: unknown | undefined, + decimatorPayload: unknown | undefined ): TaipyAction => createRequestDataUpdateAction( name, @@ -577,7 +634,7 @@ export const createRequestChartUpdateAction = ( { decimatorPayload: decimatorPayload, }, - true, + true ); export const createRequestTableUpdateAction = ( @@ -599,7 +656,7 @@ export const createRequestTableUpdateAction = ( filters?: Array, compare?: string, compareDatas?: string, - stateContext?: Record, + stateContext?: Record ): TaipyAction => createRequestDataUpdateAction( name, @@ -622,7 +679,7 @@ export const createRequestTableUpdateAction = ( compare, compare_datas: compareDatas, state_context: stateContext, - }), + }) ); export const createRequestInfiniteTableUpdateAction = ( @@ -645,7 +702,7 @@ export const createRequestInfiniteTableUpdateAction = ( compare?: string, compareDatas?: string, stateContext?: Record, - reverse?: boolean, + reverse?: boolean ): TaipyAction => createRequestDataUpdateAction( name, @@ -670,7 +727,7 @@ export const createRequestInfiniteTableUpdateAction = ( compare_datas: compareDatas, state_context: stateContext, reverse: !!reverse, - }), + }) ); /** @@ -701,7 +758,7 @@ export const createRequestDataUpdateAction = ( pageKey: string, payload: Record, allData = false, - library?: string, + library?: string ): TaipyAction => { payload = payload || {}; if (id !== undefined) { @@ -739,7 +796,7 @@ export const createRequestUpdateAction = ( context: string | undefined, names: string[], forceRefresh = false, - stateContext?: Record, + stateContext?: Record ): TaipyAction => ({ type: Types.RequestUpdate, name: "", @@ -812,7 +869,7 @@ export const createNavigateAction = ( to?: string, params?: Record, tab?: string, - force?: boolean, + force?: boolean ): TaipyNavigateAction => ({ type: Types.Navigate, to, diff --git a/frontend/taipy-gui/src/context/wsUtils.ts b/frontend/taipy-gui/src/context/wsUtils.ts index 51cdea670d..e5e8fd1ec1 100644 --- a/frontend/taipy-gui/src/context/wsUtils.ts +++ b/frontend/taipy-gui/src/context/wsUtils.ts @@ -1,5 +1,5 @@ import { Socket } from "socket.io-client"; -import { v4 as uuidv4 } from "uuid"; +import { nanoid } from 'nanoid' export const TAIPY_CLIENT_ID = "TaipyClientId"; @@ -21,7 +21,8 @@ export type WsMessageType = | "GDT" | "AID" | "GR" - | "FV"; + | "FV" + | "BC"; export interface WsMessage { type: WsMessageType; @@ -43,7 +44,7 @@ export const sendWsMessage = ( propagate = true, serverAck?: (val: unknown) => void ): string => { - const ackId = uuidv4(); + const ackId = nanoid(); const msg: WsMessage = { type: type, name: name, diff --git a/frontend/taipy-gui/src/extensions/exports.ts b/frontend/taipy-gui/src/extensions/exports.ts index ff6ddc4e6f..a7c516acd1 100644 --- a/frontend/taipy-gui/src/extensions/exports.ts +++ b/frontend/taipy-gui/src/extensions/exports.ts @@ -40,6 +40,8 @@ import { createSendUpdateAction, createRequestDataUpdateAction, createRequestUpdateAction, + createUnBroadcastAction, + BroadcastDesc } from "../context/taipyReducers"; export { @@ -53,6 +55,7 @@ export { TableSort, Metric, TaipyContext as Context, + createUnBroadcastAction, createRequestDataUpdateAction, createRequestUpdateAction, createSendActionNameAction, @@ -68,6 +71,7 @@ export { }; export type { + BroadcastDesc, ColumnDesc, FilterDesc, LoV, diff --git a/frontend/taipy/package-lock.json b/frontend/taipy/package-lock.json index f7521bd005..21a70bfaa6 100644 --- a/frontend/taipy/package-lock.json +++ b/frontend/taipy/package-lock.json @@ -41,6 +41,7 @@ } }, "../../taipy/gui/webapp": { + "name": "taipy-gui", "version": "4.0.0" }, "node_modules/@babel/code-frame": { @@ -1272,9 +1273,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.6.1.tgz", - "integrity": "sha512-V48tCfcKb/e6cVUigLAaJDAILdMP0fUW6BidkPK4GpGjXcfbnoHasCZDwz3N3yVt5we2RHm4XTQCpv0KJz9zqw==", + "version": "22.7.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", + "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", "dev": true, "dependencies": { "undici-types": "~6.19.2" @@ -1291,9 +1292,9 @@ "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" }, "node_modules/@types/react": { - "version": "18.3.8", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.8.tgz", - "integrity": "sha512-syBUrW3/XpnW4WJ41Pft+I+aPoDVbrBVQGEnbD7NijDGlVC+8gV/XKRY+7vMDlfPpbwYt0l1vd/Sj8bJGMbs9Q==", + "version": "18.3.10", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.10.tgz", + "integrity": "sha512-02sAAlBnP39JgXwkAq3PeU9DVaaGpZyF3MGcC0MKgQVkZor5IiiDAipVaxQHtDJAmO4GIy/rVBy/LzVj76Cyqg==", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -1323,16 +1324,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz", - "integrity": "sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", + "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/type-utils": "8.7.0", - "@typescript-eslint/utils": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/type-utils": "8.8.0", + "@typescript-eslint/utils": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1356,15 +1357,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.7.0.tgz", - "integrity": "sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", + "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4" }, "engines": { @@ -1384,13 +1385,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz", - "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", + "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0" + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1401,13 +1402,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz", - "integrity": "sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", + "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.7.0", - "@typescript-eslint/utils": "8.7.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/utils": "8.8.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1425,9 +1426,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz", - "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", + "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1438,13 +1439,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz", - "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", + "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1466,15 +1467,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz", - "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", + "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0" + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1488,12 +1489,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz", - "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", + "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/types": "8.8.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -2019,9 +2020,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", "dev": true, "funding": [ { @@ -2038,8 +2039,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, @@ -2084,9 +2085,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001663", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001663.tgz", - "integrity": "sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==", + "version": "1.0.30001666", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001666.tgz", + "integrity": "sha512-gD14ICmoV5ZZM1OdzPWmpx+q4GyefaK06zi8hmfHV5xe4/2nOQX3+Dw5o+fSqOws2xVwL9j+anOPFwHzdEdV4g==", "dev": true, "funding": [ { @@ -2413,9 +2414,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.28", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.28.tgz", - "integrity": "sha512-VufdJl+rzaKZoYVUijN13QcXVF5dWPZANeFTLNy+OSpHdDL5ynXTF35+60RSBbaQYB1ae723lQXHCrf4pyLsMw==", + "version": "1.5.31", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.31.tgz", + "integrity": "sha512-QcDoBbQeYt0+3CWcK/rEbuHvwpbT/8SV9T3OSgs6cX1FlcUAkgrkqbg9zLnDrMM/rLamzQwal4LYFCiWk861Tg==", "dev": true }, "node_modules/enhanced-resolve": { @@ -2691,9 +2692,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.36.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.36.1.tgz", - "integrity": "sha512-/qwbqNXZoq+VP30s1d4Nc1C5GTxjJQjk4Jzs4Wq2qzxFM7dSmuG2UkIjg2USMLh3A/aVcUNrK7v0J5U1XEGGwA==", + "version": "7.37.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.1.tgz", + "integrity": "sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==", "dev": true, "dependencies": { "array-includes": "^3.1.8", @@ -3077,9 +3078,9 @@ "dev": true }, "node_modules/fast-uri": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", - "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", + "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==", "dev": true }, "node_modules/fastest-levenshtein": { @@ -5376,9 +5377,9 @@ } }, "node_modules/terser": { - "version": "5.33.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.33.0.tgz", - "integrity": "sha512-JuPVaB7s1gdFKPKTelwUyRq5Sid2A3Gko2S0PncwdBq7kN9Ti9HPWDQ06MPsEDGsZeVESjKEnyGy68quBk1w6g==", + "version": "5.34.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.34.1.tgz", + "integrity": "sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -5762,9 +5763,9 @@ "dev": true }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -5781,8 +5782,8 @@ } ], "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -5814,9 +5815,9 @@ } }, "node_modules/webpack": { - "version": "5.94.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", - "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", + "version": "5.95.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", + "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", "dev": true, "dependencies": { "@types/estree": "^1.0.5", diff --git a/frontend/taipy/package.json b/frontend/taipy/package.json index 907c64b328..fb1cd376d2 100644 --- a/frontend/taipy/package.json +++ b/frontend/taipy/package.json @@ -30,7 +30,8 @@ "fast-deep-equal": "^3.1.3", "formik": "^2.2.9", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "taipy-gui": "file:../../taipy/gui/webapp" }, "scripts": { "postinstall": "node scripts/install.js", diff --git a/frontend/taipy/src/CoreSelector.tsx b/frontend/taipy/src/CoreSelector.tsx index 9a0f3aff5c..2577238e20 100644 --- a/frontend/taipy/src/CoreSelector.tsx +++ b/frontend/taipy/src/CoreSelector.tsx @@ -49,6 +49,7 @@ import { TableFilter, SortDesc, TableSort, + createUnBroadcastAction, } from "taipy-gui"; import { Cycles, Cycle, DataNodes, NodeType, Scenarios, Scenario, DataNode, Sequence, Sequences } from "./utils/types"; @@ -62,6 +63,7 @@ import { BadgePos, BadgeSx, BaseTreeViewSx, + CoreProps, FlagSx, ParentItemSx, getUpdateVarNames, @@ -81,25 +83,14 @@ type Entities = Cycles | Scenarios | DataNodes; type Entity = Cycle | Scenario | Sequence | DataNode; type Pinned = Record; -interface CoreSelectorProps { - id?: string; - active?: boolean; - defaultActive?: boolean; - updateVarName?: string; +interface CoreSelectorProps extends CoreProps { entities?: Entities; - coreChanged?: Record; - updateVars: string; onChange?: string; - error?: string; displayCycles?: boolean; showPrimaryFlag?: boolean; - propagate?: boolean; value?: string | string[]; defaultValue?: string; height: string; - libClassName?: string; - className?: string; - dynamicClassName?: string; multiple?: boolean; lovPropertyName: string; leafType: NodeType; @@ -167,7 +158,7 @@ const CoreItem = (props: { data-selectable={nodeType === props.leafType} label={ - + {nodeType === NodeType.CYCLE ? ( ) : nodeType === NodeType.SCENARIO ? ( @@ -441,9 +432,18 @@ const CoreSelector = (props: CoreSelectorProps) => { // Refresh on broadcast useEffect(() => { - if (coreChanged?.scenario) { - const updateVar = getUpdateVar(updateVars, lovPropertyName); - updateVar && dispatch(createRequestUpdateAction(id, module, [updateVar], true)); + if (coreChanged?.name) { + const toRemove = [...coreChanged.stack] + .map((bc) => { + if ((bc as Record).scenario) { + const updateVar = getUpdateVar(updateVars, lovPropertyName); + updateVar && dispatch(createRequestUpdateAction(id, module, [updateVar], true)); + return bc; + } + return undefined; + }) + .filter((v) => v); + toRemove.length && dispatch(createUnBroadcastAction(coreChanged.name, ...toRemove)); } }, [coreChanged, updateVars, module, dispatch, id, lovPropertyName]); @@ -712,6 +712,7 @@ const CoreSelector = (props: CoreSelectorProps) => { ) : null} + {props.children} ); }; diff --git a/frontend/taipy/src/DataNodeChart.tsx b/frontend/taipy/src/DataNodeChart.tsx index eb9846f9f3..73208c6b44 100644 --- a/frontend/taipy/src/DataNodeChart.tsx +++ b/frontend/taipy/src/DataNodeChart.tsx @@ -47,7 +47,7 @@ interface DataNodeChartProps { columns?: Record; defaultConfig?: string; updateVarName?: string; - uniqid: string; + uniqId: string; chartConfigs?: string; onViewTypeChange: (e: MouseEvent, value?: string) => void; } @@ -240,7 +240,7 @@ const getBaseConfig = (defaultConfig?: string, chartConfigs?: string, configId?: }; const DataNodeChart = (props: DataNodeChartProps) => { - const { defaultConfig = "", uniqid, configId, chartConfigs = "", onViewTypeChange } = props; + const { defaultConfig = "", uniqId, configId, chartConfigs = "", onViewTypeChange } = props; const [config, setConfig] = useState(undefined); useEffect(() => { @@ -406,7 +406,7 @@ const DataNodeChart = (props: DataNodeChartProps) => { {config?.traces && config?.types ? config?.traces.map((tc, idx) => { - const baseLabelId = `${uniqid}-trace${idx}-"`; + const baseLabelId = `${uniqId}-trace${idx}-"`; return ( diff --git a/frontend/taipy/src/DataNodeTable.tsx b/frontend/taipy/src/DataNodeTable.tsx index 6de25ef998..bd3e270c93 100644 --- a/frontend/taipy/src/DataNodeTable.tsx +++ b/frontend/taipy/src/DataNodeTable.tsx @@ -52,7 +52,7 @@ interface DataNodeTableProps { data?: Record; columns?: Record; updateVarName?: string; - uniqid: string; + uniqId: string; onEdit?: string; onViewTypeChange: (e: MouseEvent, value?: string) => void; onLock?: string; @@ -65,7 +65,7 @@ interface DataNodeTableProps { const pushRightSx = { ml: "auto" }; const DataNodeTable = (props: DataNodeTableProps) => { - const { uniqid, configId, nodeId, columns = "", onViewTypeChange, notEditableReason, updateDnVars = "" } = props; + const { uniqId, configId, nodeId, columns = "", onViewTypeChange, notEditableReason, updateDnVars = "" } = props; const dispatch = useDispatch(); const module = useModule(); @@ -108,9 +108,9 @@ const DataNodeTable = (props: DataNodeTableProps) => { useEffect(() => { if (columns) { const res = {} as Record; - const dfids = {} as Record; - Object.entries(columns).forEach(([k, v]) => (dfids[v.dfid] = k)); - selectedCols.forEach((c) => dfids[c] && (res[dfids[c]] = columns[dfids[c]])); + const dfIds = {} as Record; + Object.entries(columns).forEach(([k, v]) => (dfIds[v.dfid] = k)); + selectedCols.forEach((c) => dfIds[c] && (res[dfIds[c]] = columns[dfIds[c]])); setTabCols(res); } }, [columns, selectedCols]); @@ -164,9 +164,9 @@ const DataNodeTable = (props: DataNodeTableProps) => { - Columns + Columns