{
- // Fetch login options (will populate Vuex store)
- await store.dispatch('authProvider/fetchLoginOptions')
- // Logic from workspaceInvitationToken mixin
- const token = route.query.workspaceInvitationToken
- let invitation = null
- if (token) {
- try {
- const { data } = await WorkspaceService(
- app.$client
- ).fetchInvitationByToken(token)
- invitation = data
- } catch {}
+// Data fetching - use token in key to avoid caching issues
+const invitationToken = route.query.workspaceInvitationToken
+const { data } = await useAsyncData(
+ `loginData-${invitationToken || 'none'}`,
+ async () => {
+ // Fetch login options (will populate Vuex store)
+ await store.dispatch('authProvider/fetchLoginOptions')
+ // Logic from workspaceInvitationToken mixin
+ let invitation = null
+ if (invitationToken) {
+ try {
+ const { data } = await WorkspaceService(
+ app.$client
+ ).fetchInvitationByToken(invitationToken)
+ invitation = data
+ } catch {}
+ }
+ return { invitation }
}
- return { invitation }
-})
+)
// Head
useHead({
diff --git a/web-frontend/modules/core/pages/signup.vue b/web-frontend/modules/core/pages/signup.vue
index f0af7591ea..546b1f9b19 100644
--- a/web-frontend/modules/core/pages/signup.vue
+++ b/web-frontend/modules/core/pages/signup.vue
@@ -88,8 +88,9 @@ const displayEmailNotVerified = ref(false)
const emailToVerify = ref(null)
// Fetch invitation data based on token
+const invitationToken = route.query.workspaceInvitationToken
const { data: invitation } = await useAsyncData(
- 'workspace-invitation',
+ `signup-invitation-${invitationToken || 'none'}`,
async () => {
// Redirect if already authenticated
if (store.getters['auth/isAuthenticated']) {
@@ -101,11 +102,10 @@ const { data: invitation } = await useAsyncData(
await store.dispatch('authProvider/fetchLoginOptions')
// Fetch workspace invitation if token exists
- const token = route.query.workspaceInvitationToken
- if (token) {
+ if (invitationToken) {
try {
const { data } =
- await WorkspaceService($client).fetchInvitationByToken(token)
+ await WorkspaceService($client).fetchInvitationByToken(invitationToken)
return data
} catch {
return null
diff --git a/web-frontend/modules/core/pages/workspace.vue b/web-frontend/modules/core/pages/workspace.vue
index e5a7a8cbac..0c5bb74b79 100644
--- a/web-frontend/modules/core/pages/workspace.vue
+++ b/web-frontend/modules/core/pages/workspace.vue
@@ -229,7 +229,12 @@ import DashboardVerifyEmail from '@baserow/modules/core/components/dashboard/Das
import TemplateModal from '@baserow/modules/core/components/template/TemplateModal'
import DashboardHelp from '@baserow/modules/core/components/dashboard/DashboardHelp'
-definePageMeta({ layout: 'app' })
+definePageMeta({
+ layout: 'app',
+ // Note: these middlewares must be explicitly listed because child pages
+ // don't automatically inherit parent middleware in Nuxt 3's page meta
+ middleware: ['authenticated', 'workspacesAndApplications', 'impersonate'],
+})
defineOptions({
mixins: [editWorkspace],
diff --git a/web-frontend/modules/core/pages/workspaceInvitation.vue b/web-frontend/modules/core/pages/workspaceInvitation.vue
index 8777b41e8b..b79b6e4e94 100644
--- a/web-frontend/modules/core/pages/workspaceInvitation.vue
+++ b/web-frontend/modules/core/pages/workspaceInvitation.vue
@@ -1,35 +1,72 @@
-
diff --git a/web-frontend/modules/core/store/auth.js b/web-frontend/modules/core/store/auth.js
index be821c67bf..b1ae0f7861 100644
--- a/web-frontend/modules/core/store/auth.js
+++ b/web-frontend/modules/core/store/auth.js
@@ -140,7 +140,7 @@ export const actions = {
* Authenticate a user by his email and password.
*/
async login({ getters, dispatch }, { email, password }) {
- const { data } = await AuthService(useNuxtApp().$client).login(
+ const { data } = await AuthService(this.$client).login(
email,
password
)
@@ -181,7 +181,7 @@ export const actions = {
templateId = null,
}
) {
- const { data } = await AuthService(useNuxtApp().$client).register(
+ const { data } = await AuthService(this.$client).register(
email,
name,
password,
@@ -203,13 +203,14 @@ export const actions = {
*/
logoff({ getters, dispatch }, { invalidateToken = false }) {
const refreshToken = getters.refreshToken
+ const $client = this.$client
dispatch('forceLogoff')
if (invalidateToken) {
// Invalidate the token async because we don't have to wait for that.
setTimeout(() => {
- AuthService(useNuxtApp().$client).blacklistToken(refreshToken)
+ AuthService($client).blacklistToken(refreshToken)
})
}
},
@@ -277,7 +278,7 @@ export const actions = {
* Updates the account information is the authenticated user.
*/
async update({ getters, commit, dispatch }, values) {
- const { data } = await AuthService(useNuxtApp().$client).update(values)
+ const { data } = await AuthService(this.$client).update(values)
dispatch('forceUpdateUserData', { user: data })
dispatch(
'workspace/forceUpdateWorkspaceUserAttributes',
@@ -321,7 +322,7 @@ export const actions = {
commit('SET_USER_SESSION_EXPIRED', value)
},
async fetchWorkspaceInvitations({ commit }) {
- const { data } = await AuthService(useNuxtApp().$client).dashboard()
+ const { data } = await AuthService(this.$client).dashboard()
commit('SET_WORKSPACE_INVIATIONS', data.workspace_invitations)
return data.workspace_invitations
},
@@ -330,7 +331,7 @@ export const actions = {
},
async acceptWorkspaceInvitation({ commit }, invitationId) {
const { data: workspace } = await WorkspaceService(
- useNuxtApp().$client
+ this.$client
).acceptInvitation(invitationId)
commit('REMOVE_WORKSPACE_INVITATION', invitationId)
return workspace
@@ -339,7 +340,7 @@ export const actions = {
commit('REMOVE_WORKSPACE_INVITATION', invitation.id)
},
async rejectWorkspaceInvitation({ commit }, invitationId) {
- await WorkspaceService(useNuxtApp().$client).rejectInvitation(invitationId)
+ await WorkspaceService(this.$client).rejectInvitation(invitationId)
commit('REMOVE_WORKSPACE_INVITATION', invitationId)
},
forceRejectWorkspaceInvitation({ commit }, invitation) {
diff --git a/web-frontend/modules/dashboard/module.js b/web-frontend/modules/dashboard/module.js
index 20fbe74147..88894f12ec 100644
--- a/web-frontend/modules/dashboard/module.js
+++ b/web-frontend/modules/dashboard/module.js
@@ -39,16 +39,7 @@ import {
extendPages,
} from 'nuxt/kit'
import { routes } from './routes'
-
-const locales = [
- { code: 'en', name: 'English', file: 'en.json' },
- { code: 'fr', name: 'Français', file: 'fr.json' },
- { code: 'nl', name: 'Nederlands', file: 'nl.json' },
- { code: 'de', name: 'Deutsch', file: 'de.json' },
- { code: 'es', name: 'Español', file: 'es.json' },
- { code: 'it', name: 'Italiano', file: 'it.json' },
- { code: 'pl', name: 'Polski (Beta)', file: 'pl.json' },
-]
+import { locales } from '../../config/locales.js'
export default defineNuxtModule({
meta: {
diff --git a/web-frontend/modules/database/locales/ko.json b/web-frontend/modules/database/locales/ko.json
index f15b175aee..11fabdf57c 100644
--- a/web-frontend/modules/database/locales/ko.json
+++ b/web-frontend/modules/database/locales/ko.json
@@ -146,7 +146,7 @@
"userFieldNames": "`user_field_names` GET 매개변수를 제공하고 그 값이 다음 중 하나인 경우: `y`, `yes`, `true`, `t`, `on`, `1`, 또는 빈 문자열인 경우, 이 엔드포인트에서 반환되는 필드 이름은 실제 필드 이름이 됩니다.\n\n`user_field_names` GET 매개변수가 제공되지 않거나 위의 값 중 어느 것도 일치하지 않는 경우, 반환되는 모든 필드 이름은 `field_` 뒤에 필드의 ID가 옵니다. 예를 들어 `field_1`은 ID가 `1`인 필드를 나타냅니다.\n\n 또한 `user_field_names`가 설정되면 다른 GET 매개변수 `order_by`, `include` 및 `exclude`의 동작이 변경됩니다. 대신 실제 필드 이름의 쉼표로 구분된 목록을 기대합니다.",
"search": "제공된 경우 검색 쿼리와 일치하는 데이터가 있는 행만 반환됩니다.",
"orderBy": "선택적으로 쉼표로 구분된 필드로 행을 정렬할 수 있습니다. 기본적으로 또는 '+'가 앞에 오면 필드는 오름차순(A-Z)으로 정렬되지만, '-'가 앞에 오면 내림차순(Z-A)으로 정렬할 수 있습니다.\n\n #### `user_field_names` 사용 시:\n\n `order_by`는 정렬할 필드 이름의 쉼표로 구분된 목록이어야 합니다. 예를 들어 `order_by=My Field,-My Field 2` GET 매개변수를 제공하면 행은 `My Field`라는 필드로 오름차순으로 정렬됩니다. 일부 필드에 동일한 값이 있는 경우 해당 하위 집합은 `My Field 2`라는 필드로 내림차순으로 정렬됩니다.\n\n `+` 또는 `-`로 시작하는 필드 이름은 명시적으로 다른 `+` 또는 `-`를 앞에 붙여야 합니다. 예: `+-Name`.\n\n 쉼표를 포함하는 필드 이름은 따옴표로 묶어야 합니다: `\"Name ,\"`. 필드 이름에 따옴표가 포함된 경우 `\\` 문자를 사용하여 이스케이프해야 합니다. 예: `Name \\\"`.\n\n#### `user_field_names` 없이:\n\n `order_by`는 정렬할 필드의 ID 뒤에 `field_`가 오는 쉼표로 구분된 목록이어야 합니다. 예를 들어 `order_by=field_1,-field_2` GET 매개변수를 제공하면 행은 `field_1`로 오름차순으로 정렬됩니다. 일부 필드에 동일한 값이 있는 경우 해당 하위 집합은 `field_2`로 내림차순으로 정렬됩니다.",
- "filters": "행은 선택적으로 뷰에 사용할 수 있는 동일한 뷰 필터를 사용하여 필터링할 수 있습니다. 이 매개변수는 이 뷰에 적용할 필터 트리를 포함하는 JSON 직렬화된 문자열을 허용합니다. 필터 트리는 적용해야 하는 필터를 포함하는 중첩된 구조입니다. \n\n#### `user_field_names` 사용 시:\n\n유효한 필터 트리의 예는 다음과 같습니다: `{'{'{'}'}{'{'{'}'}'filter_type': 'AND', 'filters': [{'{'{'}'}{'{'{'}'}'field': 'Name', 'type': 'equal', 'value': 'test'{'}'}{'}'}]{'}'}{'}'}`.\n\n#### `user_field_names` 없이:\n\n예를 들어 다음 GET 매개변수를 제공하는 경우: `{'{'{'}'}{'{'{'}'}'filter_type': 'AND', 'filters': [{'{'{'}'}{'{'{'}'}'field': 1, 'type': 'equal', 'value': 'test'{'}'}{'}'}]{'}'}{'}'}`\n\n이 매개변수가 제공된 경우, 모든 다른 `filter__{field}__{filter}`는 무시되며, filter_type 매개변수도 무시됩니다.",
+ "filters": "행은 선택적으로 뷰에 사용할 수 있는 동일한 뷰 필터를 사용하여 필터링할 수 있습니다. 이 매개변수는 이 뷰에 적용할 필터 트리를 포함하는 JSON 직렬화된 문자열을 허용합니다. 필터 트리는 적용해야 하는 필터를 포함하는 중첩된 구조입니다. \n\n#### `user_field_names` 사용 시:\n\n유효한 필터 트리의 예는 다음과 같습니다: `{'{'}\"filter_type\": \"AND\", \"filters\": [{'{'}\"field\": \"Name\", \"type\": \"equal\", \"value\": \"test\"{'}'}]{'}'}`.\n\n#### `user_field_names` 없이:\n\n예를 들어 다음 GET 매개변수를 제공하는 경우: `{'{'}\"filter_type\": \"AND\", \"filters\": [{'{'}\"field\": 1, \"type\": \"equal\", \"value\": \"test\"{'}'}]{'}'}`\n\n이 매개변수가 제공된 경우, 모든 다른 `filter__{'{'}field{'}'}__{'{'}filter{'}'}` 는 무시되며, filter_type 매개변수도 무시됩니다.",
"filter": "행은 선택적으로 뷰에 사용할 수 있는 동일한 뷰 필터를 사용하여 필터링할 수 있습니다. 동일한 형식을 따르는 경우 여러 필터를 적용할 수 있습니다. `field` 및 `filter` 변수는 각각 필터를 적용할 방법과 위치를 나타냅니다.\n\n#### `user_field_names` 사용 시:\n\n예를 들어 다음 GET 매개변수를 제공하는 경우: `filter__Name__equal=test`, `Name`의 값이 'test'인 행만 반환됩니다. 이 방법은 이전 버전과 호환되며 이름에서 실패하면 `field_id`를 확인합니다.\n\n#### `user_field_names` 없이:\n\n예를 들어 다음 GET 매개변수를 제공하는 경우: `filter__field_1__equal=test`, `field_1`의 값이 'test'인 행만 반환됩니다.\n\n필터 매개변수가 제공된 경우 이 매개변수는 무시됩니다. ",
"filterLink": "모든 필터 목록은 여기에서 찾을 수 있습니다.",
"filterType": "- `AND`: 제공된 모든 필터와 일치해야 함을 나타냅니다.\n- `OR`: 필터 중 하나와만 일치하면 됨을 나타냅니다.\n\n 이는 두 개 이상의 필터가 제공된 경우에만 작동합니다.",
diff --git a/web-frontend/modules/database/module.js b/web-frontend/modules/database/module.js
index df78fd22c9..4c427a204f 100644
--- a/web-frontend/modules/database/module.js
+++ b/web-frontend/modules/database/module.js
@@ -39,16 +39,7 @@ import {
extendPages,
} from 'nuxt/kit'
import { routes } from './routes'
-
-const locales = [
- { code: 'en', name: 'English', file: 'en.json' },
- { code: 'fr', name: 'Français', file: 'fr.json' },
- { code: 'nl', name: 'Nederlands', file: 'nl.json' },
- { code: 'de', name: 'Deutsch', file: 'de.json' },
- { code: 'es', name: 'Español', file: 'es.json' },
- { code: 'it', name: 'Italiano', file: 'it.json' },
- { code: 'pl', name: 'Polski (Beta)', file: 'pl.json' },
-]
+import { locales } from '../../config/locales.js'
export default defineNuxtModule({
meta: {
diff --git a/web-frontend/modules/integrations/module.js b/web-frontend/modules/integrations/module.js
index 061067f931..b272f1ed1e 100644
--- a/web-frontend/modules/integrations/module.js
+++ b/web-frontend/modules/integrations/module.js
@@ -1,15 +1,5 @@
import { defineNuxtModule, addPlugin, createResolver } from 'nuxt/kit'
-
-const locales = [
- { code: 'en', name: 'English', file: 'en.json' },
- { code: 'fr', name: 'Français', file: 'fr.json' },
- { code: 'nl', name: 'Nederlands', file: 'nl.json' },
- { code: 'de', name: 'Deutsch', file: 'de.json' },
- { code: 'es', name: 'Español', file: 'es.json' },
- { code: 'it', name: 'Italiano', file: 'it.json' },
- { code: 'pl', name: 'Polski (Beta)', file: 'pl.json' },
- { code: 'ko', name: '한국어', file: 'ko.json' },
-]
+import { locales } from '../../config/locales.js'
export default defineNuxtModule({
meta: {