Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: pick up the URL variables at the start of the app - WF-55 #538

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 29 additions & 9 deletions src/ui/src/components/core/root/CoreRoot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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.";

Expand All @@ -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,
Expand All @@ -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);
Expand All @@ -100,7 +120,7 @@ const displayedPageId = computed(() => {
});

function handleHashChange() {
const parsedHash = getParsedHash();
const parsedHash = serializeParsedHash();
const event = new CustomEvent("wf-hashchange", {
detail: {
payload: parsedHash,
Expand Down
31 changes: 31 additions & 0 deletions src/ui/src/core/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,23 @@ type ParsedHash = {
routeVars: Map<string, string>; // Stored as Map to avoid injection e.g. prototype pollution
};

// Use to communicate with the backend
type SerializedHash = {
pageKey?: string;
routeVars: Record<string, string>;
};

const hashRegex = /^((?<pageKey>[^/]*))?(\/(?<routeVars>.*))?$/;
const routeVarRegex = /^(?<key>[^=]+)=(?<value>.*)$/;

/**
* 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;
Expand All @@ -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;

Expand Down
32 changes: 30 additions & 2 deletions src/ui/src/renderer/ComponentRenderer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,25 @@
</template>

<script setup lang="ts">
import { inject, ref, computed, watch, ComputedRef, onBeforeMount } from "vue";
import {
inject,
ref,
computed,
watch,
ComputedRef,
onBeforeMount,
onMounted,
} from "vue";
import { Component } from "@/writerTypes";
import ComponentProxy from "./ComponentProxy.vue";
import RendererNotifications from "./RendererNotifications.vue";
import injectionKeys from "@/injectionKeys";
import { useEvaluator } from "./useEvaluator";
import { changePageInHash, changeRouteVarsInHash } from "@/core/navigation";
import {
changePageInHash,
changeRouteVarsInHash,
serializeParsedHash,
} from "@/core/navigation";

const wf = inject(injectionKeys.core);
const wfbm = inject(injectionKeys.builderManager);
Expand Down Expand Up @@ -203,9 +215,25 @@ function addMailSubscriptions() {
);
}

function handleAppOpenChange() {
const parsedHash = serializeParsedHash();
const event = new CustomEvent("wf-app-open", {
detail: {
payload: parsedHash,
},
});

const rootInstance = { componentId: "root", instanceNumber: 0 };
wf.forwardEvent(event, [rootInstance], true);
}

onBeforeMount(() => {
addMailSubscriptions();
});

onMounted(() => {
handleAppOpenChange();
});
</script>

<style scoped>
Expand Down
10 changes: 10 additions & 0 deletions src/writer/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1306,6 +1306,16 @@ def _transform_page_open(self, ev) -> str:
payload = str(ev.payload)
return payload

def _transform_app_open(self, ev) -> dict:
payload = ev.payload
page_key = payload.get("pageKey")
route_vars = dict(payload.get("routeVars"))
tf_payload = {
"page_key": page_key,
"route_vars": route_vars
}
return tf_payload

def _transform_chatbot_message(self, ev) -> dict:
payload = dict(ev.payload)
return payload
Expand Down
Loading