From a729fa583a9146b24a9e79e3b805ccd2f7344d96 Mon Sep 17 00:00:00 2001 From: JulienChampagnol Date: Fri, 18 Jul 2025 17:24:21 +0200 Subject: [PATCH 01/13] feat(stores): app_mode wip --- components/Recaptcha.vue | 5 ++--- nuxt.config.js | 1 - stores/geode.js | 13 ++++--------- stores/infra.js | 4 +--- stores/viewer.js | 9 +-------- utils/app_mode.js | 14 ++++++++++++++ 6 files changed, 22 insertions(+), 24 deletions(-) create mode 100644 utils/app_mode.js diff --git a/components/Recaptcha.vue b/components/Recaptcha.vue index a3a0d55b..f32cc77d 100644 --- a/components/Recaptcha.vue +++ b/components/Recaptcha.vue @@ -20,9 +20,8 @@ }) onMounted(() => { - if (process.client) { - const config = useRuntimeConfig() - if (config.public.NODE_ENV !== "production" || !infra_store.is_cloud) { + if (import.meta.client) { + if (process.env.NODE_ENV !== "production" || !infra_store.is_cloud) { infra_store.$patch({ is_captcha_validated: true }) } } diff --git a/nuxt.config.js b/nuxt.config.js index 00b9314d..e3d6a6e2 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -5,7 +5,6 @@ export default defineNuxtConfig({ SITE_BRANCH: process.env.NODE_ENV === "production" ? process.env.SITE_BRANCH : "", PROJECT: process.env.NODE_ENV === "production" ? process.env.PROJECT : "", - NODE_ENV: process.env.NODE_ENV, }, }, diff --git a/stores/geode.js b/stores/geode.js index 7dd51b38..b2acf676 100644 --- a/stores/geode.js +++ b/stores/geode.js @@ -1,29 +1,24 @@ import back_schemas from "@geode/opengeodeweb-back/schemas.json" import Status from "@ogw_f/utils/status.js" +import appMode from "@ogw_f/utils/app_mode.js" export const use_geode_store = defineStore("geode", { state: () => ({ - default_local_port: "5000", + port: "443", request_counter: 0, status: Status.NOT_CONNECTED, }), getters: { protocol() { - if (use_infra_store().is_cloud) { + if (use_infra_store().app_mode == appMode.CLOUD) { return "https" } return "http" }, - port() { - if (use_infra_store().is_cloud) { - return "443" - } - return this.default_local_port - }, base_url() { const infra_store = use_infra_store() let geode_url = `${this.protocol}://${infra_store.domain_name}:${this.port}` - if (infra_store.is_cloud) { + if (infra_store.app_mode == appMode.CLOUD) { if (infra_store.ID == "") { throw new Error("ID must not be empty in cloud mode") } diff --git a/stores/infra.js b/stores/infra.js index b9f3d602..c35e0f3f 100644 --- a/stores/infra.js +++ b/stores/infra.js @@ -10,9 +10,7 @@ export const use_infra_store = defineStore("infra", { }), getters: { is_cloud() { - return ( - !isElectron() && useRuntimeConfig().public.NODE_ENV === "production" - ) + return !isElectron() && useRuntimeConfig().public.APP_ENV === "production" }, domain_name() { if (this.is_cloud) { diff --git a/stores/viewer.js b/stores/viewer.js index 4460b7ae..573913d8 100644 --- a/stores/viewer.js +++ b/stores/viewer.js @@ -6,7 +6,7 @@ import Status from "@ogw_f/utils/status.js" export const use_viewer_store = defineStore("viewer", { state: () => ({ - default_local_port: "1234", + port: "443", client: {}, config: null, picking_mode: false, @@ -22,13 +22,6 @@ export const use_viewer_store = defineStore("viewer", { return "ws" } }, - port() { - if (use_infra_store().is_cloud) { - return "443" - } else { - return this.default_local_port - } - }, base_url() { const infra_store = use_infra_store() let viewer_url = `${this.protocol}://${infra_store.domain_name}:${this.port}` diff --git a/utils/app_mode.js b/utils/app_mode.js new file mode 100644 index 00000000..bd816c42 --- /dev/null +++ b/utils/app_mode.js @@ -0,0 +1,14 @@ +import isElectron from "is-electron" + +const appMode = { + DESKTOP: "DESKTOP", + BROWSER: "BROWSER", + CLOUD: "CLOUD", +} + +function getAppMode() { + if (isElectron()) { + return appMode.DESKTOP + } +} +export default { appMode, getAppMode } From 2e759854beb52ef8c692d5e0c5bc9a5be9a9e8db Mon Sep 17 00:00:00 2001 From: JulienChampagnol Date: Mon, 21 Jul 2025 15:53:41 +0200 Subject: [PATCH 02/13] recaptcha enabled only in cloud mode --- components/Recaptcha.vue | 8 -------- 1 file changed, 8 deletions(-) diff --git a/components/Recaptcha.vue b/components/Recaptcha.vue index f32cc77d..4102a551 100644 --- a/components/Recaptcha.vue +++ b/components/Recaptcha.vue @@ -19,14 +19,6 @@ site_key: { type: String, required: true }, }) - onMounted(() => { - if (import.meta.client) { - if (process.env.NODE_ENV !== "production" || !infra_store.is_cloud) { - infra_store.$patch({ is_captcha_validated: true }) - } - } - }) - async function submit_recaptcha(token) { try { const response = await $fetch.raw( From 2972142f89e2aece9abe552e0bdc33fc3221e73d Mon Sep 17 00:00:00 2001 From: JulienChampagnol Date: Mon, 21 Jul 2025 15:53:57 +0200 Subject: [PATCH 03/13] appMode --- stores/infra.js | 53 +++++++++++++++++++++++++---------------------- stores/viewer.js | 3 ++- utils/app_mode.js | 4 ++++ 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/stores/infra.js b/stores/infra.js index c35e0f3f..e697d324 100644 --- a/stores/infra.js +++ b/stores/infra.js @@ -1,19 +1,18 @@ import { useStorage } from "@vueuse/core" import isElectron from "is-electron" import Status from "@ogw_f/utils/status.js" +import { appMode, getAppMode } from "@ogw_f/utils/app_mode.js" export const use_infra_store = defineStore("infra", { state: () => ({ + app_mode: getAppMode(), ID: useStorage("ID", ""), - is_captcha_validated: false, + is_captcha_validated: this.app_mode != appMode.CLOUD ? true : false, status: Status.NOT_CREATED, }), getters: { - is_cloud() { - return !isElectron() && useRuntimeConfig().public.APP_ENV === "production" - }, domain_name() { - if (this.is_cloud) { + if (this.app_mode == appMode.CLOUD) { return useRuntimeConfig().public.API_URL } else { return "localhost" @@ -50,27 +49,31 @@ export const use_infra_store = defineStore("infra", { this.status = Status.CREATING if (this.status === Status.CREATED) return console.log("LOCK GRANTED !", lock) - const geode_store = use_geode_store() - const viewer_store = use_viewer_store() - const feedback_store = use_feedback_store() - if (isElectron()) { - const back_port = await window.electronAPI.run_back(geode_store.port) - geode_store.$patch({ default_local_port: back_port }) - const viewer_port = await window.electronAPI.run_viewer( - viewer_store.port, - ) - viewer_store.$patch({ default_local_port: viewer_port }) - } else { - const { data, error } = await useFetch(this.lambda_url, { - method: "POST", - }) - if (error.value || !data.value) { - this.status = Status.NOT_CREATED - feedback_store.server_error = true - return + if (this.app_mode != appMode.BROWSER) { + const geode_store = use_geode_store() + const viewer_store = use_viewer_store() + const feedback_store = use_feedback_store() + if (isElectron()) { + const back_port = await window.electronAPI.run_back( + geode_store.port, + ) + geode_store.$patch({ default_local_port: back_port }) + const viewer_port = await window.electronAPI.run_viewer( + viewer_store.port, + ) + viewer_store.$patch({ default_local_port: viewer_port }) + } else { + const { data, error } = await useFetch(this.lambda_url, { + method: "POST", + }) + if (error.value || !data.value) { + this.status = Status.NOT_CREATED + feedback_store.server_error = true + return + } + this.ID = data.value.ID + localStorage.setItem("ID", data.value.ID) } - this.ID = data.value.ID - localStorage.setItem("ID", data.value.ID) } this.status = Status.CREATED return this.create_connection() diff --git a/stores/viewer.js b/stores/viewer.js index 573913d8..d8d48418 100644 --- a/stores/viewer.js +++ b/stores/viewer.js @@ -3,6 +3,7 @@ import vtkWSLinkClient from "@kitware/vtk.js/IO/Core/WSLinkClient" import "@kitware/vtk.js/Rendering/OpenGL/Profiles/Geometry" import schemas from "@geode/opengeodeweb-viewer/schemas.json" import Status from "@ogw_f/utils/status.js" +import appMode from "@ogw_f/utils/app_mode.js" export const use_viewer_store = defineStore("viewer", { state: () => ({ @@ -16,7 +17,7 @@ export const use_viewer_store = defineStore("viewer", { }), getters: { protocol() { - if (use_infra_store().is_cloud) { + if (use_infra_store().app_mode == appMode.CLOUD) { return "wss" } else { return "ws" diff --git a/utils/app_mode.js b/utils/app_mode.js index bd816c42..5ae69968 100644 --- a/utils/app_mode.js +++ b/utils/app_mode.js @@ -10,5 +10,9 @@ function getAppMode() { if (isElectron()) { return appMode.DESKTOP } + if (process.env.BROWSER === true) { + return appMode.BROWSER + } + return appMode.CLOUD } export default { appMode, getAppMode } From 55474ce5264c0ad03786c3150e2752cc4adc6e60 Mon Sep 17 00:00:00 2001 From: JulienChampagnol Date: Thu, 24 Jul 2025 13:26:18 +0200 Subject: [PATCH 04/13] wip refactor --- components/Launcher.vue | 7 +++++- stores/geode.js | 3 +-- stores/infra.js | 53 ++++++++++++++++++++--------------------- stores/viewer.js | 3 +-- utils/app_mode.js | 4 ++-- 5 files changed, 36 insertions(+), 34 deletions(-) diff --git a/components/Launcher.vue b/components/Launcher.vue index 21e63b74..676ef30a 100644 --- a/components/Launcher.vue +++ b/components/Launcher.vue @@ -24,10 +24,15 @@ const infra_store = use_infra_store() const site_key = useRuntimeConfig().public.RECAPTCHA_SITE_KEY + if (import.meta.client) { + if (infra_store.is_captcha_validated) { + infra_store.create_backend() + } + } watch( () => infra_store.is_captcha_validated, (value, oldValue) => { - if (value && !oldValue && process.client) { + if (value && !oldValue && import.meta.client) { infra_store.create_backend() } }, diff --git a/stores/geode.js b/stores/geode.js index b2acf676..167a4497 100644 --- a/stores/geode.js +++ b/stores/geode.js @@ -1,10 +1,9 @@ import back_schemas from "@geode/opengeodeweb-back/schemas.json" import Status from "@ogw_f/utils/status.js" -import appMode from "@ogw_f/utils/app_mode.js" export const use_geode_store = defineStore("geode", { state: () => ({ - port: "443", + port: "99", request_counter: 0, status: Status.NOT_CONNECTED, }), diff --git a/stores/infra.js b/stores/infra.js index e697d324..17118b8d 100644 --- a/stores/infra.js +++ b/stores/infra.js @@ -1,13 +1,11 @@ import { useStorage } from "@vueuse/core" -import isElectron from "is-electron" import Status from "@ogw_f/utils/status.js" -import { appMode, getAppMode } from "@ogw_f/utils/app_mode.js" export const use_infra_store = defineStore("infra", { state: () => ({ app_mode: getAppMode(), ID: useStorage("ID", ""), - is_captcha_validated: this.app_mode != appMode.CLOUD ? true : false, + is_captcha_validated: true, status: Status.NOT_CREATED, }), getters: { @@ -44,42 +42,43 @@ export const use_infra_store = defineStore("infra", { }, actions: { async create_backend() { + console.log("create_backend") if (this.status === Status.CREATED) return return navigator.locks.request("infra.create_backend", async (lock) => { this.status = Status.CREATING if (this.status === Status.CREATED) return console.log("LOCK GRANTED !", lock) - if (this.app_mode != appMode.BROWSER) { - const geode_store = use_geode_store() - const viewer_store = use_viewer_store() - const feedback_store = use_feedback_store() - if (isElectron()) { - const back_port = await window.electronAPI.run_back( - geode_store.port, - ) - geode_store.$patch({ default_local_port: back_port }) - const viewer_port = await window.electronAPI.run_viewer( - viewer_store.port, - ) - viewer_store.$patch({ default_local_port: viewer_port }) - } else { - const { data, error } = await useFetch(this.lambda_url, { - method: "POST", - }) - if (error.value || !data.value) { - this.status = Status.NOT_CREATED - feedback_store.server_error = true - return - } - this.ID = data.value.ID - localStorage.setItem("ID", data.value.ID) + // if (this.app_mode != appMode.BROWSER) { + const geode_store = use_geode_store() + const viewer_store = use_viewer_store() + const feedback_store = use_feedback_store() + if (this.app_mode == appMode.CLOUD) { + const back_port = await window.electronAPI.run_back(geode_store.port) + geode_store.$patch({ default_local_port: back_port }) + const viewer_port = await window.electronAPI.run_viewer( + viewer_store.port, + ) + viewer_store.$patch({ default_local_port: viewer_port }) + } else { + const { data, error } = await useFetch(this.lambda_url, { + method: "POST", + }) + if (error.value || !data.value) { + this.status = Status.NOT_CREATED + feedback_store.server_error = true + return } + this.ID = data.value.ID + localStorage.setItem("ID", data.value.ID) } + // } this.status = Status.CREATED + console.log("this.status", this.status) return this.create_connection() }) }, async create_connection() { + console.log("create_connection") await use_viewer_store().ws_connect() await use_geode_store().do_ping() return diff --git a/stores/viewer.js b/stores/viewer.js index d8d48418..6f6bd0a3 100644 --- a/stores/viewer.js +++ b/stores/viewer.js @@ -3,11 +3,10 @@ import vtkWSLinkClient from "@kitware/vtk.js/IO/Core/WSLinkClient" import "@kitware/vtk.js/Rendering/OpenGL/Profiles/Geometry" import schemas from "@geode/opengeodeweb-viewer/schemas.json" import Status from "@ogw_f/utils/status.js" -import appMode from "@ogw_f/utils/app_mode.js" export const use_viewer_store = defineStore("viewer", { state: () => ({ - port: "443", + port: "99", client: {}, config: null, picking_mode: false, diff --git a/utils/app_mode.js b/utils/app_mode.js index 5ae69968..057b0bf9 100644 --- a/utils/app_mode.js +++ b/utils/app_mode.js @@ -1,12 +1,12 @@ import isElectron from "is-electron" -const appMode = { +export const appMode = { DESKTOP: "DESKTOP", BROWSER: "BROWSER", CLOUD: "CLOUD", } -function getAppMode() { +export function getAppMode() { if (isElectron()) { return appMode.DESKTOP } From 72a3f32fba0eca83c27872567bb9372f2ea34574 Mon Sep 17 00:00:00 2001 From: JulienChampagnol Date: Fri, 25 Jul 2025 15:21:02 +0200 Subject: [PATCH 05/13] wip refactor --- components/Launcher.vue | 5 ----- stores/geode.js | 9 ++++++--- stores/infra.js | 13 +++++++------ stores/viewer.js | 8 ++++++-- utils/app_mode.js | 1 + 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/components/Launcher.vue b/components/Launcher.vue index 676ef30a..eebdb73a 100644 --- a/components/Launcher.vue +++ b/components/Launcher.vue @@ -24,11 +24,6 @@ const infra_store = use_infra_store() const site_key = useRuntimeConfig().public.RECAPTCHA_SITE_KEY - if (import.meta.client) { - if (infra_store.is_captcha_validated) { - infra_store.create_backend() - } - } watch( () => infra_store.is_captcha_validated, (value, oldValue) => { diff --git a/stores/geode.js b/stores/geode.js index 9b73b2bf..9dd29b55 100644 --- a/stores/geode.js +++ b/stores/geode.js @@ -3,13 +3,13 @@ import Status from "@ogw_f/utils/status.js" export const use_geode_store = defineStore("geode", { state: () => ({ - port: "99", + port: "443", request_counter: 0, status: Status.NOT_CONNECTED, }), getters: { protocol() { - if (use_infra_store().app_mode == appMode.CLOUD) { + if (use_infra_store().app_mode == appMode.appMode.CLOUD) { return "https" } return "http" @@ -17,12 +17,15 @@ export const use_geode_store = defineStore("geode", { base_url() { const infra_store = use_infra_store() let geode_url = `${this.protocol}://${infra_store.domain_name}:${this.port}` - if (infra_store.app_mode == appMode.CLOUD) { + if (infra_store.app_mode == appMode.appMode.CLOUD) { if (infra_store.ID == "") { throw new Error("ID must not be empty in cloud mode") } geode_url += `/${infra_store.ID}/geode` } + if (infra_store.app_mode == appMode.appMode.BROWSER) { + geode_url += `/geode` + } return geode_url }, is_busy() { diff --git a/stores/infra.js b/stores/infra.js index 17118b8d..bb60c435 100644 --- a/stores/infra.js +++ b/stores/infra.js @@ -5,16 +5,15 @@ export const use_infra_store = defineStore("infra", { state: () => ({ app_mode: getAppMode(), ID: useStorage("ID", ""), - is_captcha_validated: true, + is_captcha_validated: this.app_mode == appMode.appMode.CLOUD ? false : true, status: Status.NOT_CREATED, }), getters: { domain_name() { - if (this.app_mode == appMode.CLOUD) { + if (this.app_mode == appMode.appMode.CLOUD) { return useRuntimeConfig().public.API_URL - } else { - return "localhost" } + return "localhost" }, lambda_url() { const geode_store = use_geode_store() @@ -44,6 +43,7 @@ export const use_infra_store = defineStore("infra", { async create_backend() { console.log("create_backend") if (this.status === Status.CREATED) return + console.log("1") return navigator.locks.request("infra.create_backend", async (lock) => { this.status = Status.CREATING if (this.status === Status.CREATED) return @@ -52,14 +52,15 @@ export const use_infra_store = defineStore("infra", { const geode_store = use_geode_store() const viewer_store = use_viewer_store() const feedback_store = use_feedback_store() - if (this.app_mode == appMode.CLOUD) { + if (this.app_mode == appMode.appMode.DESKTOP) { const back_port = await window.electronAPI.run_back(geode_store.port) geode_store.$patch({ default_local_port: back_port }) const viewer_port = await window.electronAPI.run_viewer( viewer_store.port, ) viewer_store.$patch({ default_local_port: viewer_port }) - } else { + } + if (this.app_mode == appMode.appMode.CLOUD) { const { data, error } = await useFetch(this.lambda_url, { method: "POST", }) diff --git a/stores/viewer.js b/stores/viewer.js index 283cbd59..357efa8f 100644 --- a/stores/viewer.js +++ b/stores/viewer.js @@ -16,7 +16,7 @@ export const use_viewer_store = defineStore("viewer", { }), getters: { protocol() { - if (use_infra_store().app_mode == appMode.CLOUD) { + if (use_infra_store().app_mode == appMode.appMode.CLOUD) { return "wss" } else { return "ws" @@ -24,13 +24,17 @@ export const use_viewer_store = defineStore("viewer", { }, base_url() { const infra_store = use_infra_store() + let viewer_url = `${this.protocol}://${infra_store.domain_name}:${this.port}` - if (infra_store.is_cloud) { + if (infra_store.app_mode == appMode.appMode.CLOUD) { if (infra_store.ID == "") { throw new Error("ID must not be empty in cloud mode") } viewer_url += `/${infra_store.ID}/viewer` } + if (infra_store.app_mode == appMode.appMode.BROWSER) { + viewer_url += `/viewer` + } viewer_url += "/ws" return viewer_url }, diff --git a/utils/app_mode.js b/utils/app_mode.js index 057b0bf9..07254a25 100644 --- a/utils/app_mode.js +++ b/utils/app_mode.js @@ -7,6 +7,7 @@ export const appMode = { } export function getAppMode() { + console.log("getAppMode process.env", process.env) if (isElectron()) { return appMode.DESKTOP } From f59be2210aa41abf1845527b4d66d088010d0e3e Mon Sep 17 00:00:00 2001 From: JulienChampagnol Date: Wed, 30 Jul 2025 13:36:37 +0200 Subject: [PATCH 06/13] stores & composables --- composables/api_fetch.js | 5 +++++ composables/viewer_call.js | 5 +++++ nuxt.config.js | 3 +++ stores/geode.js | 14 ++++++++++---- stores/infra.js | 23 ++++++++--------------- stores/viewer.js | 16 +++++++++++----- utils/app_mode.js | 3 +-- 7 files changed, 43 insertions(+), 26 deletions(-) diff --git a/composables/api_fetch.js b/composables/api_fetch.js index 5728246c..b997e67a 100644 --- a/composables/api_fetch.js +++ b/composables/api_fetch.js @@ -12,6 +12,11 @@ export function api_fetch( const { valid, error } = validate_schema(schema, body) if (!valid) { + if (process.env.NODE_ENV === "development") { + console.log("Bad request", error, schema, params) + console.log("schema", schema) + console.log("params", params) + } feedback_store.add_error(400, schema.$id, "Bad request", error) throw new Error(schema.$id.concat(": ", error)) } diff --git a/composables/viewer_call.js b/composables/viewer_call.js index e59501d3..6b281bc8 100644 --- a/composables/viewer_call.js +++ b/composables/viewer_call.js @@ -8,6 +8,11 @@ export function viewer_call( const { valid, error } = validate_schema(schema, params) if (!valid) { + if (process.env.NODE_ENV === "development") { + console.log("Bad request", error, schema, params) + console.log("schema", schema) + console.log("params", params) + } feedback_store.add_error(400, schema.route, "Bad request", error) throw new Error(schema.route.concat(": ", error)) } diff --git a/nuxt.config.js b/nuxt.config.js index e3d6a6e2..f0fb5685 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -5,6 +5,9 @@ export default defineNuxtConfig({ SITE_BRANCH: process.env.NODE_ENV === "production" ? process.env.SITE_BRANCH : "", PROJECT: process.env.NODE_ENV === "production" ? process.env.PROJECT : "", + BROWSER: process.env.BROWSER || false, + GEODE_PORT: process.env.GEODE_PORT || "", + VIEWER_PORT: process.env.VIEWER_PORT || "", }, }, diff --git a/stores/geode.js b/stores/geode.js index 9dd29b55..7c55f25f 100644 --- a/stores/geode.js +++ b/stores/geode.js @@ -3,7 +3,7 @@ import Status from "@ogw_f/utils/status.js" export const use_geode_store = defineStore("geode", { state: () => ({ - port: "443", + default_local_port: "5000", request_counter: 0, status: Status.NOT_CONNECTED, }), @@ -14,6 +14,15 @@ export const use_geode_store = defineStore("geode", { } return "http" }, + port() { + if (use_infra_store().app_mode == appMode.appMode.CLOUD) { + return "443" + } + if (useRuntimeConfig().public.GEODE_PORT) { + return useRuntimeConfig().public.GEODE_PORT + } + return this.default_local_port + }, base_url() { const infra_store = use_infra_store() let geode_url = `${this.protocol}://${infra_store.domain_name}:${this.port}` @@ -23,9 +32,6 @@ export const use_geode_store = defineStore("geode", { } geode_url += `/${infra_store.ID}/geode` } - if (infra_store.app_mode == appMode.appMode.BROWSER) { - geode_url += `/geode` - } return geode_url }, is_busy() { diff --git a/stores/infra.js b/stores/infra.js index bb60c435..7c7633c8 100644 --- a/stores/infra.js +++ b/stores/infra.js @@ -5,7 +5,7 @@ export const use_infra_store = defineStore("infra", { state: () => ({ app_mode: getAppMode(), ID: useStorage("ID", ""), - is_captcha_validated: this.app_mode == appMode.appMode.CLOUD ? false : true, + is_captcha_validated: true, status: Status.NOT_CREATED, }), getters: { @@ -41,40 +41,33 @@ export const use_infra_store = defineStore("infra", { }, actions: { async create_backend() { - console.log("create_backend") + console.log("create_backend this.app_mode", this.app_mode) if (this.status === Status.CREATED) return - console.log("1") return navigator.locks.request("infra.create_backend", async (lock) => { this.status = Status.CREATING if (this.status === Status.CREATED) return console.log("LOCK GRANTED !", lock) - // if (this.app_mode != appMode.BROWSER) { - const geode_store = use_geode_store() - const viewer_store = use_viewer_store() - const feedback_store = use_feedback_store() if (this.app_mode == appMode.appMode.DESKTOP) { - const back_port = await window.electronAPI.run_back(geode_store.port) + const viewer_store = use_viewer_store() + const geode_store = use_geode_store() + const back_port = await window.electronAPI.run_back(geode_store.default_local_port) geode_store.$patch({ default_local_port: back_port }) - const viewer_port = await window.electronAPI.run_viewer( - viewer_store.port, - ) + const viewer_port = await window.electronAPI.run_viewer(viewer_store.default_local_port) viewer_store.$patch({ default_local_port: viewer_port }) - } - if (this.app_mode == appMode.appMode.CLOUD) { + } else if (this.app_mode == appMode.appMode.CLOUD) { const { data, error } = await useFetch(this.lambda_url, { method: "POST", }) if (error.value || !data.value) { this.status = Status.NOT_CREATED + const feedback_store = use_feedback_store() feedback_store.server_error = true return } this.ID = data.value.ID localStorage.setItem("ID", data.value.ID) } - // } this.status = Status.CREATED - console.log("this.status", this.status) return this.create_connection() }) }, diff --git a/stores/viewer.js b/stores/viewer.js index 357efa8f..deb29ee0 100644 --- a/stores/viewer.js +++ b/stores/viewer.js @@ -3,10 +3,11 @@ import vtkWSLinkClient from "@kitware/vtk.js/IO/Core/WSLinkClient" import "@kitware/vtk.js/Rendering/OpenGL/Profiles/Geometry" import schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" import Status from "@ogw_f/utils/status.js" +import { useRuntimeConfig } from "nuxt/app" export const use_viewer_store = defineStore("viewer", { state: () => ({ - port: "99", + default_local_port: "1234", client: {}, config: null, picking_mode: false, @@ -22,9 +23,17 @@ export const use_viewer_store = defineStore("viewer", { return "ws" } }, + port() { + if (use_infra_store().app_mode == appMode.appMode.CLOUD) { + return "443" + } + if (useRuntimeConfig().public.VIEWER_PORT) { + return useRuntimeConfig().public.VIEWER_PORT + } + return this.default_local_port + }, base_url() { const infra_store = use_infra_store() - let viewer_url = `${this.protocol}://${infra_store.domain_name}:${this.port}` if (infra_store.app_mode == appMode.appMode.CLOUD) { if (infra_store.ID == "") { @@ -32,9 +41,6 @@ export const use_viewer_store = defineStore("viewer", { } viewer_url += `/${infra_store.ID}/viewer` } - if (infra_store.app_mode == appMode.appMode.BROWSER) { - viewer_url += `/viewer` - } viewer_url += "/ws" return viewer_url }, diff --git a/utils/app_mode.js b/utils/app_mode.js index 07254a25..7fd563b3 100644 --- a/utils/app_mode.js +++ b/utils/app_mode.js @@ -7,11 +7,10 @@ export const appMode = { } export function getAppMode() { - console.log("getAppMode process.env", process.env) if (isElectron()) { return appMode.DESKTOP } - if (process.env.BROWSER === true) { + if (useRuntimeConfig().public.BROWSER === "true") { return appMode.BROWSER } return appMode.CLOUD From 307155183b01dce61d78992813b89fbc20c60742 Mon Sep 17 00:00:00 2001 From: JulienChampagnol Date: Wed, 30 Jul 2025 14:51:04 +0200 Subject: [PATCH 07/13] feat(app_mode): wip fix unit tests --- test/stores/Geode.nuxt.test.js | 40 +++++++++++++++++----------- test/stores/Infra.nuxt.test.js | 19 ++++++------- test/stores/Viewer.nuxt.test.js | 47 ++++++++++++++++++++++----------- 3 files changed, 65 insertions(+), 41 deletions(-) diff --git a/test/stores/Geode.nuxt.test.js b/test/stores/Geode.nuxt.test.js index c6d0f9bf..2a1e9cb6 100644 --- a/test/stores/Geode.nuxt.test.js +++ b/test/stores/Geode.nuxt.test.js @@ -28,52 +28,60 @@ describe("Geode Store", () => { }) }) + describe("getters", () => { describe("protocol", () => { - test("test is_cloud true", () => { - infra_store.is_cloud = true + test("test app_mode CLOUD", () => { + infra_store.app_mode = appMode.appMode.CLOUD expect(geode_store.protocol).toBe("https") }) - - test("test is_cloud false", () => { - infra_store.is_cloud = false + test("test app_mode BROWSER", () => { + infra_store.app_mode = appMode.appMode.BROWSER + expect(geode_store.protocol).toBe("http") + }) + test("test app_mode DESKTOP", () => { + infra_store.app_mode = appMode.appMode.DESKTOP expect(geode_store.protocol).toBe("http") }) }) describe("port", () => { - test("test is_cloud true", () => { - infra_store.is_cloud = true + test("test app_mode CLOUD", () => { + infra_store.app_mode = appMode.appMode.CLOUD expect(geode_store.port).toBe("443") }) - test("test is_cloud false", () => { - infra_store.is_cloud = false + test("test app_mode BROWSER", () => { + infra_store.app_mode = appMode.appMode.BROWSER + expect(geode_store.port).toBe(geode_store.default_local_port) + }) + test("test app_mode DESKTOP", () => { + infra_store.app_mode = appMode.appMode.DESKTOP expect(geode_store.port).toBe(geode_store.default_local_port) }) test("test override default_local_port", () => { - infra_store.is_cloud = false + infra_store.app_mode = appMode.appMode.DESKTOP geode_store.default_local_port = "12" expect(geode_store.port).toBe("12") }) }) describe("base_url", () => { - test("test is_cloud false", () => { - infra_store.is_cloud = false + test("test app_mode BROWSER", () => { + infra_store.app_mode = appMode.appMode.BROWSER infra_store.domain_name = "localhost" expect(geode_store.base_url).toBe("http://localhost:5000") }) - test("test is_cloud true", () => { - infra_store.is_cloud = true + test("test app_mode CLOUD", () => { + infra_store.app_mode = appMode.appMode.CLOUD infra_store.ID = "123456" infra_store.domain_name = "example.com" expect(geode_store.base_url).toBe( "https://example.com:443/123456/geode", ) }) - test("test is_cloud true, ID empty", () => { - infra_store.is_cloud = true + test("test app_mode CLOUD, ID empty", () => { + infra_store.app_mode = appMode.appMode.CLOUD infra_store.ID = "" infra_store.domain_name = "example.com" expect(() => geode_store.base_url).toThrowError( diff --git a/test/stores/Infra.nuxt.test.js b/test/stores/Infra.nuxt.test.js index 2c8517ce..7b2c19cb 100644 --- a/test/stores/Infra.nuxt.test.js +++ b/test/stores/Infra.nuxt.test.js @@ -40,22 +40,23 @@ describe("Infra Store", () => { }) }) describe("getters", () => { - describe("is_cloud", () => { + describe("app_mode", () => { test("test type", () => { - expectTypeOf(infra_store.is_cloud).toBeBoolean() + expectTypeOf(infra_store.app_mode).toBeString() }) }) describe("domain_name", () => { - test("test type", () => { - expectTypeOf(infra_store.is_cloud).toBeString() + test("test app_mode BROWSER", () => { + infra_store.app_mode = appMode.appMode.BROWSER + expect(infra_store.domain_name).toBe("localhost") }) - test("test is_cloud false", () => { - infra_store.is_cloud = false + test("test app_mode DESKTOP", () => { + infra_store.app_mode = appMode.appMode.DESKTOP expect(infra_store.domain_name).toBe("localhost") }) - test("test is_cloud false", () => { - infra_store.is_cloud = true + test("test app_mode CLOUD", () => { + infra_store.app_mode = appMode.appMode.CLOUD expect(infra_store.domain_name).toBe("api.geode-solutions.com") }) }) @@ -64,7 +65,7 @@ describe("Infra Store", () => { test("test is cloud true", () => { useRuntimeConfig().public.SITE_BRANCH = "/test" useRuntimeConfig().public.PROJECT = "/project" - infra_store.is_cloud = true + infra_store.app_mode = appMode.appMode.CLOUD expect(infra_store.lambda_url).toBe( "https://api.geode-solutions.com:443/test/project/createbackend", ) diff --git a/test/stores/Viewer.nuxt.test.js b/test/stores/Viewer.nuxt.test.js index b926e3ec..f3673f48 100644 --- a/test/stores/Viewer.nuxt.test.js +++ b/test/stores/Viewer.nuxt.test.js @@ -1,6 +1,7 @@ import { setActivePinia } from "pinia" import { createTestingPinia } from "@pinia/testing" import { describe, test, expect, expectTypeOf, beforeEach } from "vitest" +import { useRuntimeConfig } from "nuxt/app" describe("Viewer Store", () => { const pinia = createTestingPinia({ @@ -30,42 +31,56 @@ describe("Viewer Store", () => { describe("getters", () => { describe("protocol", () => { - test("test is_cloud true", () => { - infra_store.is_cloud = true + test("test app_mode CLOUD", () => { + infra_store.app_mode = appMode.appMode.CLOUD expect(viewer_store.protocol).toBe("wss") }) - - test("test is_cloud false", () => { - infra_store.is_cloud = false + test("test app_mode BROWSER", () => { + infra_store.app_mode = appMode.appMode.BROWSER + expect(viewer_store.protocol).toBe("ws") + }) + test("test app_mode DESKTOP", () => { + infra_store.app_mode = appMode.appMode.DESKTOP expect(viewer_store.protocol).toBe("ws") }) }) describe("port", () => { - test("test is_cloud true", () => { - infra_store.is_cloud = true + test("test app_mode CLOUD", () => { + infra_store.app_mode = appMode.appMode.CLOUD expect(viewer_store.port).toBe("443") }) - test("test is_cloud false", () => { - infra_store.is_cloud = false + test("test app_mode BROWSER", () => { + infra_store.app_mode = appMode.appMode.BROWSER + expect(viewer_store.port).toBe(viewer_store.default_local_port) + }) + test("test app_mode DESKTOP", () => { + infra_store.app_mode = appMode.appMode.DESKTOP expect(viewer_store.port).toBe(viewer_store.default_local_port) }) test("test override default_local_port", () => { - infra_store.is_cloud = false + infra_store.app_mode = appMode.appMode.DESKTOP viewer_store.default_local_port = "8080" expect(viewer_store.port).toBe("8080") }) + + test("test env VIEWER_PORT", () => { + process.env.VIEWER_PORT = "8080" + infra_store.app_mode = appMode.appMode.DESKTOP + console.log("VIEWER_PORT", useRuntimeConfig().public.VIEWER_PORT) + expect(viewer_store.port).toBe("8080") + }) }) describe("base_url", () => { - test("test is_cloud false", () => { - infra_store.is_cloud = false + test("test app_mode DESKTOP", () => { + infra_store.app_mode = appMode.appMode.DESKTOP infra_store.domain_name = "localhost" expect(viewer_store.base_url).toBe("ws://localhost:1234/ws") }) - test("test is_cloud true", () => { - infra_store.is_cloud = true + test("test app_mode CLOUD", () => { + infra_store.app_mode = appMode.appMode.CLOUD infra_store.ID = "123456" infra_store.domain_name = "example.com" expect(viewer_store.base_url).toBe( @@ -73,8 +88,8 @@ describe("Viewer Store", () => { ) }) - test("test is_cloud true, ID empty", () => { - infra_store.is_cloud = true + test("test app_mode CLOUD, ID empty", () => { + infra_store.app_mode = appMode.appMode.CLOUD infra_store.ID = "" infra_store.domain_name = "example.com" expect(() => viewer_store.base_url).toThrowError( From d6a742d5c904cd33059c6c7dfbd62ac6d1e3a03b Mon Sep 17 00:00:00 2001 From: JulienChampagnol <91873154+JulienChampagnol@users.noreply.github.com> Date: Wed, 30 Jul 2025 12:52:04 +0000 Subject: [PATCH 08/13] Apply prepare changes --- stores/infra.js | 8 ++++++-- test/stores/Geode.nuxt.test.js | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/stores/infra.js b/stores/infra.js index 7c7633c8..5af73dff 100644 --- a/stores/infra.js +++ b/stores/infra.js @@ -50,9 +50,13 @@ export const use_infra_store = defineStore("infra", { if (this.app_mode == appMode.appMode.DESKTOP) { const viewer_store = use_viewer_store() const geode_store = use_geode_store() - const back_port = await window.electronAPI.run_back(geode_store.default_local_port) + const back_port = await window.electronAPI.run_back( + geode_store.default_local_port, + ) geode_store.$patch({ default_local_port: back_port }) - const viewer_port = await window.electronAPI.run_viewer(viewer_store.default_local_port) + const viewer_port = await window.electronAPI.run_viewer( + viewer_store.default_local_port, + ) viewer_store.$patch({ default_local_port: viewer_port }) } else if (this.app_mode == appMode.appMode.CLOUD) { const { data, error } = await useFetch(this.lambda_url, { diff --git a/test/stores/Geode.nuxt.test.js b/test/stores/Geode.nuxt.test.js index 2a1e9cb6..8e3be3b3 100644 --- a/test/stores/Geode.nuxt.test.js +++ b/test/stores/Geode.nuxt.test.js @@ -28,7 +28,6 @@ describe("Geode Store", () => { }) }) - describe("getters", () => { describe("protocol", () => { test("test app_mode CLOUD", () => { From 15dd9fced7c7532ae95fb79c880ad133e6253de7 Mon Sep 17 00:00:00 2001 From: JulienChampagnol Date: Wed, 30 Jul 2025 15:00:37 +0200 Subject: [PATCH 09/13] import.meta.client --- components/RemoteRenderingView.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/RemoteRenderingView.vue b/components/RemoteRenderingView.vue index adcd55fb..3379b01d 100644 --- a/components/RemoteRenderingView.vue +++ b/components/RemoteRenderingView.vue @@ -108,7 +108,7 @@ } onMounted(async () => { - if (process.client) { + if (import.meta.client) { window.addEventListener("resize", resize) await nextTick() view.setContainer(viewer.value.$el) From 5efeabcd0a4e468ed37e046adf86a166ecaa6b5f Mon Sep 17 00:00:00 2001 From: JulienChampagnol Date: Thu, 31 Jul 2025 10:48:57 +0200 Subject: [PATCH 10/13] tests passing --- nuxt.config.js | 6 +++--- stores/geode.js | 5 +++-- stores/infra.js | 3 ++- stores/viewer.js | 6 +++--- test/components/Launcher.nuxt.test.js | 4 ++-- test/stores/Viewer.nuxt.test.js | 8 -------- utils/captcha_state.js | 11 +++++++++++ 7 files changed, 24 insertions(+), 19 deletions(-) create mode 100644 utils/captcha_state.js diff --git a/nuxt.config.js b/nuxt.config.js index f0fb5685..2d2cddb1 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -5,9 +5,9 @@ export default defineNuxtConfig({ SITE_BRANCH: process.env.NODE_ENV === "production" ? process.env.SITE_BRANCH : "", PROJECT: process.env.NODE_ENV === "production" ? process.env.PROJECT : "", - BROWSER: process.env.BROWSER || false, - GEODE_PORT: process.env.GEODE_PORT || "", - VIEWER_PORT: process.env.VIEWER_PORT || "", + BROWSER: process.env.BROWSER ?? false, + GEODE_PORT: process.env.GEODE_PORT ?? null, + VIEWER_PORT: process.env.VIEWER_PORT ?? null, }, }, diff --git a/stores/geode.js b/stores/geode.js index 7c55f25f..cc7dad2d 100644 --- a/stores/geode.js +++ b/stores/geode.js @@ -18,8 +18,9 @@ export const use_geode_store = defineStore("geode", { if (use_infra_store().app_mode == appMode.appMode.CLOUD) { return "443" } - if (useRuntimeConfig().public.GEODE_PORT) { - return useRuntimeConfig().public.GEODE_PORT + const GEODE_PORT = useRuntimeConfig().public.GEODE_PORT + if (GEODE_PORT != null && GEODE_PORT !== "") { + return GEODE_PORT } return this.default_local_port }, diff --git a/stores/infra.js b/stores/infra.js index 5af73dff..22ada660 100644 --- a/stores/infra.js +++ b/stores/infra.js @@ -1,11 +1,12 @@ import { useStorage } from "@vueuse/core" import Status from "@ogw_f/utils/status.js" +import getCaptchaState from "@ogw_f/utils/captcha_state.js" export const use_infra_store = defineStore("infra", { state: () => ({ app_mode: getAppMode(), ID: useStorage("ID", ""), - is_captcha_validated: true, + is_captcha_validated: getCaptchaState(), status: Status.NOT_CREATED, }), getters: { diff --git a/stores/viewer.js b/stores/viewer.js index deb29ee0..7234a3d4 100644 --- a/stores/viewer.js +++ b/stores/viewer.js @@ -3,7 +3,6 @@ import vtkWSLinkClient from "@kitware/vtk.js/IO/Core/WSLinkClient" import "@kitware/vtk.js/Rendering/OpenGL/Profiles/Geometry" import schemas from "@geode/opengeodeweb-viewer/opengeodeweb_viewer_schemas.json" import Status from "@ogw_f/utils/status.js" -import { useRuntimeConfig } from "nuxt/app" export const use_viewer_store = defineStore("viewer", { state: () => ({ @@ -27,8 +26,9 @@ export const use_viewer_store = defineStore("viewer", { if (use_infra_store().app_mode == appMode.appMode.CLOUD) { return "443" } - if (useRuntimeConfig().public.VIEWER_PORT) { - return useRuntimeConfig().public.VIEWER_PORT + const VIEWER_PORT = useRuntimeConfig().public.VIEWER_PORT + if (VIEWER_PORT != null && VIEWER_PORT !== "") { + return VIEWER_PORT } return this.default_local_port }, diff --git a/test/components/Launcher.nuxt.test.js b/test/components/Launcher.nuxt.test.js index 7ba329c8..a784949b 100644 --- a/test/components/Launcher.nuxt.test.js +++ b/test/components/Launcher.nuxt.test.js @@ -31,7 +31,7 @@ global.ResizeObserver = require("resize-observer-polyfill") describe("Launcher.vue", async () => { test(`Mount`, async () => { - const spy_infra_store = vi.spyOn(infra_store, "create_backend") + const spy_create_backend = vi.spyOn(infra_store, "create_backend") const wrapper = await mountSuspended(Launcher, { global: { plugins: [vuetify], @@ -40,6 +40,6 @@ describe("Launcher.vue", async () => { expect(wrapper.exists()).toBe(true) await infra_store.$patch({ is_captcha_validated: true }) flushPromises() - expect(spy_infra_store).toHaveBeenCalled() + expect(spy_create_backend).toHaveBeenCalled() }) }) diff --git a/test/stores/Viewer.nuxt.test.js b/test/stores/Viewer.nuxt.test.js index f3673f48..b8e54f7e 100644 --- a/test/stores/Viewer.nuxt.test.js +++ b/test/stores/Viewer.nuxt.test.js @@ -1,7 +1,6 @@ import { setActivePinia } from "pinia" import { createTestingPinia } from "@pinia/testing" import { describe, test, expect, expectTypeOf, beforeEach } from "vitest" -import { useRuntimeConfig } from "nuxt/app" describe("Viewer Store", () => { const pinia = createTestingPinia({ @@ -64,13 +63,6 @@ describe("Viewer Store", () => { viewer_store.default_local_port = "8080" expect(viewer_store.port).toBe("8080") }) - - test("test env VIEWER_PORT", () => { - process.env.VIEWER_PORT = "8080" - infra_store.app_mode = appMode.appMode.DESKTOP - console.log("VIEWER_PORT", useRuntimeConfig().public.VIEWER_PORT) - expect(viewer_store.port).toBe("8080") - }) }) describe("base_url", () => { test("test app_mode DESKTOP", () => { diff --git a/utils/captcha_state.js b/utils/captcha_state.js new file mode 100644 index 00000000..3b23d9d0 --- /dev/null +++ b/utils/captcha_state.js @@ -0,0 +1,11 @@ +function getCaptchaState() { + if ( + getAppMode() === appMode.appMode.BROWSER || + getAppMode() === appMode.appMode.DESKTOP + ) { + return true + } + return false +} + +export default getCaptchaState From 0442e9862105b76a04df8e7d41cc579072d3895f Mon Sep 17 00:00:00 2001 From: JulienChampagnol Date: Thu, 31 Jul 2025 16:14:30 +0200 Subject: [PATCH 11/13] fix(app_launch): revert recaptcha --- components/Recaptcha.vue | 10 ++++++++++ stores/infra.js | 2 +- utils/captcha_state.js | 11 ----------- 3 files changed, 11 insertions(+), 12 deletions(-) delete mode 100644 utils/captcha_state.js diff --git a/components/Recaptcha.vue b/components/Recaptcha.vue index 4102a551..7c561d65 100644 --- a/components/Recaptcha.vue +++ b/components/Recaptcha.vue @@ -19,6 +19,16 @@ site_key: { type: String, required: true }, }) + onMounted(() => { + if (import.meta.client) { + if ( + process.env.NODE_ENV !== "production" || + !infra_store.app_mode !== appMode.appMode.CLOUD + ) { + infra_store.$patch({ is_captcha_validated: true }) + } + } + }) async function submit_recaptcha(token) { try { const response = await $fetch.raw( diff --git a/stores/infra.js b/stores/infra.js index 22ada660..79f7ef93 100644 --- a/stores/infra.js +++ b/stores/infra.js @@ -6,7 +6,7 @@ export const use_infra_store = defineStore("infra", { state: () => ({ app_mode: getAppMode(), ID: useStorage("ID", ""), - is_captcha_validated: getCaptchaState(), + is_captcha_validated: false, status: Status.NOT_CREATED, }), getters: { diff --git a/utils/captcha_state.js b/utils/captcha_state.js deleted file mode 100644 index 3b23d9d0..00000000 --- a/utils/captcha_state.js +++ /dev/null @@ -1,11 +0,0 @@ -function getCaptchaState() { - if ( - getAppMode() === appMode.appMode.BROWSER || - getAppMode() === appMode.appMode.DESKTOP - ) { - return true - } - return false -} - -export default getCaptchaState From c70a1fa45cac4bec29046589da4b448dbd66a915 Mon Sep 17 00:00:00 2001 From: JulienChampagnol Date: Thu, 31 Jul 2025 16:16:49 +0200 Subject: [PATCH 12/13] fix(app_launch): revert recaptcha --- components/Recaptcha.vue | 10 ++++++++++ stores/infra.js | 3 +-- utils/captcha_state.js | 11 ----------- 3 files changed, 11 insertions(+), 13 deletions(-) delete mode 100644 utils/captcha_state.js diff --git a/components/Recaptcha.vue b/components/Recaptcha.vue index 4102a551..7c561d65 100644 --- a/components/Recaptcha.vue +++ b/components/Recaptcha.vue @@ -19,6 +19,16 @@ site_key: { type: String, required: true }, }) + onMounted(() => { + if (import.meta.client) { + if ( + process.env.NODE_ENV !== "production" || + !infra_store.app_mode !== appMode.appMode.CLOUD + ) { + infra_store.$patch({ is_captcha_validated: true }) + } + } + }) async function submit_recaptcha(token) { try { const response = await $fetch.raw( diff --git a/stores/infra.js b/stores/infra.js index 22ada660..faa6c13b 100644 --- a/stores/infra.js +++ b/stores/infra.js @@ -1,12 +1,11 @@ import { useStorage } from "@vueuse/core" import Status from "@ogw_f/utils/status.js" -import getCaptchaState from "@ogw_f/utils/captcha_state.js" export const use_infra_store = defineStore("infra", { state: () => ({ app_mode: getAppMode(), ID: useStorage("ID", ""), - is_captcha_validated: getCaptchaState(), + is_captcha_validated: false, status: Status.NOT_CREATED, }), getters: { diff --git a/utils/captcha_state.js b/utils/captcha_state.js deleted file mode 100644 index 3b23d9d0..00000000 --- a/utils/captcha_state.js +++ /dev/null @@ -1,11 +0,0 @@ -function getCaptchaState() { - if ( - getAppMode() === appMode.appMode.BROWSER || - getAppMode() === appMode.appMode.DESKTOP - ) { - return true - } - return false -} - -export default getCaptchaState From d4d391fd372fe2db248a540b490bc62f3101f357 Mon Sep 17 00:00:00 2001 From: JulienChampagnol Date: Thu, 31 Jul 2025 16:31:57 +0200 Subject: [PATCH 13/13] fix(typo): Recaptcha component --- components/Recaptcha.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Recaptcha.vue b/components/Recaptcha.vue index 7c561d65..893a1126 100644 --- a/components/Recaptcha.vue +++ b/components/Recaptcha.vue @@ -23,7 +23,7 @@ if (import.meta.client) { if ( process.env.NODE_ENV !== "production" || - !infra_store.app_mode !== appMode.appMode.CLOUD + infra_store.app_mode !== appMode.appMode.CLOUD ) { infra_store.$patch({ is_captcha_validated: true }) }