diff --git a/src/ui/src/components/core/root/CoreRoot.vue b/src/ui/src/components/core/root/CoreRoot.vue index 8e3573694..69f051466 100644 --- a/src/ui/src/components/core/root/CoreRoot.vue +++ b/src/ui/src/components/core/root/CoreRoot.vue @@ -17,15 +17,14 @@ import { useEvaluator } from "@/renderer/useEvaluator"; const ssHashChangeStub = ` def handle_hashchange(state, payload): # The payload is a dictionary with the page key and all the route variables in the URL hash. - # For example, if the current URL is - # http://localhost:3000/#main/animal=duck&colour=yellow + # For example, if the current URL is http://localhost:3000/#main/animal=duck&colour=yellow # you will get the following dictionary # { - # "page_key": "main", - # "route_vars": { - # "animal": "duck", - # "colour": "yellow" - # } + # "page_key": "main", + # "route_vars": { + # "animal": "duck", + # "colour": "yellow" + # } # } page_key = payload.get("page_key") @@ -39,6 +38,23 @@ def handle_hashchange(state, payload): else: state["message"] = "You're not in the Duck zone.`.trim(); +const wfAppOpenStub = ` +def handle_app_open(state): + # The payload is a dictionary with the page key and all the route variables in the URL hash. + # For example, if the current URL is http://localhost:3000/#/animal=duck&colour=yellow + # you will get the following dictionary + # { + # "page_key": "main", + # "route_vars": { + # "animal": "duck", + # "colour": "yellow" + # } + # } + + page_key = payload.get("page_key") + route_vars = payload.get("route_vars") +`.trim(); + const description = "The root component of the application, which serves as the starting point of the component hierarchy."; @@ -57,6 +73,10 @@ export default { ...sharedStyleFields, }, events: { + "wf-app-open": { + desc: "Captures the first application load, including page key and route vars.", + stub: wfAppOpenStub, + }, "wf-hashchange": { desc: "Capture changes to the URL hash, including page key and route vars.", stub: ssHashChangeStub, @@ -76,7 +96,7 @@ import { onBeforeMount, } from "vue"; import injectionKeys from "@/injectionKeys"; -import { changePageInHash, getParsedHash } from "@/core/navigation"; +import { changePageInHash, serializeParsedHash } from "@/core/navigation"; const wf = inject(injectionKeys.core); const ssbm = inject(injectionKeys.builderManager); @@ -100,7 +120,7 @@ const displayedPageId = computed(() => { }); function handleHashChange() { - const parsedHash = getParsedHash(); + const parsedHash = serializeParsedHash(); const event = new CustomEvent("wf-hashchange", { detail: { payload: parsedHash, diff --git a/src/ui/src/core/navigation.ts b/src/ui/src/core/navigation.ts index f74b01563..dd9b0dee7 100644 --- a/src/ui/src/core/navigation.ts +++ b/src/ui/src/core/navigation.ts @@ -3,9 +3,23 @@ type ParsedHash = { routeVars: Map; // Stored as Map to avoid injection e.g. prototype pollution }; +// Use to communicate with the backend +type SerializedHash = { + pageKey?: string; + routeVars: Record; +}; + const hashRegex = /^((?[^/]*))?(\/(?.*))?$/; const routeVarRegex = /^(?[^=]+)=(?.*)$/; +/** + * Parses the current URL hash + * + * * http://x.x.x.x:5000/#main/var1=value1&var2=value2 + * + * pageKey: "main" + * routeVars: { var1: "value1", var2: "value2" } + */ export function getParsedHash(): ParsedHash { const docHash = document.location.hash.substring(1); const hashMatchGroups = docHash.match(hashRegex)?.groups; @@ -29,6 +43,23 @@ export function getParsedHash(): ParsedHash { return { pageKey, routeVars }; } +/** + * Serializes the URL information into a JSON.stringify-compatible object. + * + * It's used to send the current URL information to the server. + * + * @example + * ```ts + * const serializedHash = serializeParsedHash(); + * const urlinfoString = JSON.stringify(serializedHash); + * ``` + */ +export function serializeParsedHash(): SerializedHash { + const parsedHash = getParsedHash(); + const routeVars = Object.fromEntries(parsedHash.routeVars.entries()); + return { pageKey: parsedHash.pageKey, routeVars }; +} + function setHash(parsedHash: ParsedHash) { const { pageKey, routeVars } = parsedHash; diff --git a/src/ui/src/renderer/ComponentRenderer.vue b/src/ui/src/renderer/ComponentRenderer.vue index ce7f4bbef..0729687eb 100644 --- a/src/ui/src/renderer/ComponentRenderer.vue +++ b/src/ui/src/renderer/ComponentRenderer.vue @@ -22,13 +22,25 @@