From 358a51a6dc343a56eba795c156e07d0ce1dcbb9a Mon Sep 17 00:00:00 2001
From: Bram Wiepjes <bramw@protonmail.com>
Date: Tue, 1 Apr 2025 21:57:51 +0200
Subject: [PATCH] fixed element not found bug

---
 web-frontend/modules/core/module.js           |  1 +
 web-frontend/modules/core/plugin.js           |  2 ++
 .../modules/core/plugins/routeMounted.js      | 36 +++++++++++++++++++
 .../modules/core/store/routeMounted.js        | 24 +++++++++++++
 .../modules/database/guidedTourTypes.js       |  7 ++--
 5 files changed, 68 insertions(+), 2 deletions(-)
 create mode 100644 web-frontend/modules/core/plugins/routeMounted.js
 create mode 100644 web-frontend/modules/core/store/routeMounted.js

diff --git a/web-frontend/modules/core/module.js b/web-frontend/modules/core/module.js
index 2fba59d2a..c30083ccc 100644
--- a/web-frontend/modules/core/module.js
+++ b/web-frontend/modules/core/module.js
@@ -221,6 +221,7 @@ export default function CoreModule(options) {
   this.appendPlugin({ src: path.resolve(__dirname, 'plugins/posthog.js') })
   this.appendPlugin({ src: path.resolve(__dirname, 'plugins/router.js') })
   this.appendPlugin({ src: path.resolve(__dirname, 'plugins/version.js') })
+  this.appendPlugin({ src: path.resolve(__dirname, 'plugins/routeMounted.js') })
 
   this.extendRoutes((configRoutes) => {
     // Remove all the routes created by nuxt.
diff --git a/web-frontend/modules/core/plugin.js b/web-frontend/modules/core/plugin.js
index a78b1f331..a77f5e755 100644
--- a/web-frontend/modules/core/plugin.js
+++ b/web-frontend/modules/core/plugin.js
@@ -76,6 +76,7 @@ import integrationStore from '@baserow/modules/core/store/integration'
 import userSourceStore from '@baserow/modules/core/store/userSource'
 import notificationStore from '@baserow/modules/core/store/notification'
 import userSourceUserStore from '@baserow/modules/core/store/userSourceUser'
+import routeMounted from '@baserow/modules/core/store/routeMounted'
 
 import en from '@baserow/modules/core/locales/en.json'
 import fr from '@baserow/modules/core/locales/fr.json'
@@ -203,6 +204,7 @@ export default (context, inject) => {
   store.registerModule('userSource', userSourceStore)
   store.registerModule('notification', notificationStore)
   store.registerModule('userSourceUser', userSourceUserStore)
+  store.registerModule('routeMounted', routeMounted)
 
   registry.register('authProvider', new PasswordAuthProviderType(context))
   registry.register('job', new DuplicateApplicationJobType(context))
diff --git a/web-frontend/modules/core/plugins/routeMounted.js b/web-frontend/modules/core/plugins/routeMounted.js
new file mode 100644
index 000000000..fa5716317
--- /dev/null
+++ b/web-frontend/modules/core/plugins/routeMounted.js
@@ -0,0 +1,36 @@
+import Vue from 'vue'
+
+/**
+ * This is a global mixin that's registered for every component. The purpose is to
+ * bind to the `mounted` hook and set the related route to the `routeMounted` store.
+ * This is used so that there is a reactive state of the mounted route. It can be
+ * used by any other process to reactively check if a route has fully loaded and is
+ * mounted, which can be needed if it depends on DOM elements to be rendered.
+ */
+Vue.mixin({
+  mounted() {
+    if (
+      this.$options.__file &&
+      this.$route &&
+      // Skip components that don't have a layout because those are not Nuxt pages.
+      this.$options.layout !== undefined
+    ) {
+      this.$store.commit('routeMounted/SET_ROUTE_MOUNTED', {
+        mounted: true,
+        route: this.$route,
+      })
+    }
+  },
+  beforeDestroy() {
+    if (
+      this.$options.__file &&
+      this.$route &&
+      this.$options.layout !== undefined
+    ) {
+      this.$store.commit('routeMounted/SET_ROUTE_MOUNTED', {
+        mounted: false,
+        route: null,
+      })
+    }
+  },
+})
diff --git a/web-frontend/modules/core/store/routeMounted.js b/web-frontend/modules/core/store/routeMounted.js
new file mode 100644
index 000000000..e9458f2a0
--- /dev/null
+++ b/web-frontend/modules/core/store/routeMounted.js
@@ -0,0 +1,24 @@
+export const state = () => ({
+  routeComponentMounted: false,
+  currentRoute: null,
+})
+
+export const mutations = {
+  SET_ROUTE_MOUNTED(state, { mounted, route }) {
+    state.routeComponentMounted = mounted
+    state.currentRoute = route
+  },
+}
+
+export const getters = {
+  routeMounted(state) {
+    return state.routeComponentMounted ? state.currentRoute : null
+  },
+}
+
+export default {
+  namespaced: true,
+  state,
+  getters,
+  mutations,
+}
diff --git a/web-frontend/modules/database/guidedTourTypes.js b/web-frontend/modules/database/guidedTourTypes.js
index 8fff57957..444367241 100644
--- a/web-frontend/modules/database/guidedTourTypes.js
+++ b/web-frontend/modules/database/guidedTourTypes.js
@@ -155,9 +155,12 @@ export class DatabaseGuidedTourType extends GuidedTourType {
     return 200
   }
 
-  isActive(route) {
+  isActive() {
     return (
-      route.name === 'database-table' &&
+      // Use the `routeMounted` because that gives us the route that's actually
+      // mounted, making sure that the selector elements have been rendered.
+      this.app.store.getters['routeMounted/routeMounted']?.name ===
+        'database-table' &&
       // This tour is only compatible with the grid view.
       this.app.store.getters['view/getSelected']?.type ===
         GridViewType.getType()