diff --git a/packages/nc-gui/composables/useProject.ts b/packages/nc-gui/composables/useProject.ts index 9d073426e3..d452d5c6b1 100644 --- a/packages/nc-gui/composables/useProject.ts +++ b/packages/nc-gui/composables/useProject.ts @@ -1,31 +1,53 @@ import type { MaybeRef } from '@vueuse/core' -import { SqlUiFactory } from 'nocodb-sdk' import type { OracleUi, ProjectType, TableType } from 'nocodb-sdk' -import { useNuxtApp, useRoute } from '#app' -import type { ProjectMetaInfo } from '~/lib' +import { SqlUiFactory } from 'nocodb-sdk' +import { isString } from '@vueuse/core' +import { + USER_PROJECT_ROLES, + computed, + createEventHook, + ref, + useApi, + useGlobal, + useInjectionState, + useNuxtApp, + useRoute, + useState, + useTheme, + watch, +} from '#imports' +import type { ProjectMetaInfo, Roles } from '~/lib' import type { ThemeConfig } from '@/composables/useTheme' -import { createEventHook, useInjectionState } from '#imports' const [setup, use] = useInjectionState((_projectId?: MaybeRef) => { - const { $api, $e } = useNuxtApp() + const { $e } = useNuxtApp() + + const { api, isLoading } = useApi() + const route = useRoute() + const { includeM2M } = useGlobal() + const { setTheme, theme } = useTheme() const projectLoadedHook = createEventHook() - const projectId = computed(() => (_projectId ? unref(_projectId) : (route.params.projectId as string))) const project = ref({}) + const tables = ref([]) - const projectRoles = useState>(USER_PROJECT_ROLES, () => ({})) + + const projectRoles = useState(USER_PROJECT_ROLES, () => ({})) + const projectMetaInfo = ref() + const projectId = computed(() => (_projectId ? unref(_projectId) : (route.params.projectId as string))) + // todo: refactor path param name and variable name const projectType = $computed(() => route.params.projectType as string) - const projectMeta = computed(() => { + const projectMeta = computed>(() => { try { - return typeof project.value.meta === 'string' ? JSON.parse(project.value.meta) : project.value.meta + return project.value.meta && isString(project.value.meta) ? JSON.parse(project.value.meta) : project.value.meta } catch (e) { return {} } @@ -44,15 +66,15 @@ const [setup, use] = useInjectionState((_projectId?: MaybeRef) => { async function loadProjectMetaInfo(force?: boolean) { if (!projectMetaInfo.value || force) { - const data = await $api.project.metaGet(project.value.id!, {}, {}) - projectMetaInfo.value = data + projectMetaInfo.value = await api.project.metaGet(project.value.id!, {}, {}) } } async function loadProjectRoles() { projectRoles.value = {} + if (isSharedBase.value) { - const user = await $api.auth.me( + const user = await api.auth.me( {}, { headers: { @@ -60,33 +82,40 @@ const [setup, use] = useInjectionState((_projectId?: MaybeRef) => { }, }, ) + projectRoles.value = user.roles } else if (project.value.id) { - const user = await $api.auth.me({ project_id: project.value.id }) + const user = await api.auth.me({ project_id: project.value.id }) projectRoles.value = user.roles } } async function loadTables() { if (project.value.id) { - const tablesResponse = await $api.dbTable.list(project.value.id, { + const tablesResponse = await api.dbTable.list(project.value.id, { includeM2M: includeM2M.value, }) + if (tablesResponse.list) tables.value = tablesResponse.list } } - async function loadProject() { - if (projectType === 'base') { - const baseData = await $api.public.sharedBaseGet(route.params.projectId as string) - project.value = await $api.project.read(baseData.project_id!) + async function loadProject(id?: string) { + if (id) { + project.value = await api.project.read(projectId.value) + } else if (projectType === 'base') { + const baseData = await api.public.sharedBaseGet(route.params.projectId as string) + project.value = await api.project.read(baseData.project_id!) } else if (projectId.value) { - project.value = await $api.project.read(projectId.value) + project.value = await api.project.read(projectId.value) } else { return } + await loadProjectRoles() + await loadTables() + setTheme(projectMeta.value?.theme) projectLoadedHook.trigger(project.value) @@ -97,15 +126,13 @@ const [setup, use] = useInjectionState((_projectId?: MaybeRef) => { return } if (data.meta && typeof data.meta === 'string') { - await $api.project.update(projectId.value, data) + await api.project.update(projectId.value, data) } else { - await $api.project.update(projectId.value, { ...data, meta: JSON.stringify(data.meta) }) + await api.project.update(projectId.value, { ...data, meta: JSON.stringify(data.meta) }) } } async function saveTheme(_theme: Partial) { - $e('c:themes:change') - const fullTheme = { primaryColor: theme.value.primaryColor, accentColor: theme.value.accentColor, @@ -119,25 +146,30 @@ const [setup, use] = useInjectionState((_projectId?: MaybeRef) => { theme: fullTheme, }, }) + setTheme(fullTheme) + + $e('c:themes:change') } watch( () => route.params, - (v) => { - if (!v?.projectId) { + (next) => { + if (!next.projectId) { setTheme() } }, ) - // TODO useProject should only called inside a project for now this doesn't work - onScopeDispose(() => { + const reset = () => { project.value = {} tables.value = [] projectMetaInfo.value = undefined projectRoles.value = {} - }) + } + + // TODO useProject should only called inside a project for now this doesn't work + // onScopeDispose(reset) return { project, @@ -156,6 +188,8 @@ const [setup, use] = useInjectionState((_projectId?: MaybeRef) => { projectMeta, saveTheme, projectLoadedHook: projectLoadedHook.on, + reset, + isLoading, } }, 'useProject') diff --git a/packages/nc-gui/composables/useViewData.ts b/packages/nc-gui/composables/useViewData.ts index 5bd5340d8e..b33fe25bb0 100644 --- a/packages/nc-gui/composables/useViewData.ts +++ b/packages/nc-gui/composables/useViewData.ts @@ -1,8 +1,6 @@ import type { Api, ColumnType, FormType, GalleryType, PaginatedType, TableType, ViewType } from 'nocodb-sdk' import type { ComputedRef, Ref } from 'vue' import { message } from 'ant-design-vue' -import { useI18n } from 'vue-i18n' -import { useNuxtApp } from '#app' import { IsPublicInj, NOCO, @@ -10,6 +8,8 @@ import { extractSdkResponseErrorMsg, getHTMLEncodedText, useApi, + useI18n, + useNuxtApp, useProject, useUIPermission, } from '#imports' diff --git a/packages/nc-gui/pages/[projectType]/[projectId]/index.vue b/packages/nc-gui/pages/[projectType]/[projectId]/index.vue index 37f731b86d..de2455f182 100644 --- a/packages/nc-gui/pages/[projectType]/[projectId]/index.vue +++ b/packages/nc-gui/pages/[projectType]/[projectId]/index.vue @@ -5,6 +5,8 @@ import { computed, definePageMeta, navigateTo, + onBeforeMount, + onBeforeUnmount, onKeyStroke, openLink, projectThemeColors, @@ -16,6 +18,7 @@ import { useI18n, useProject, useRoute, + useRouter, useTabs, useUIPermission, } from '#imports' @@ -29,9 +32,20 @@ const { t } = useI18n() const route = useRoute() +const router = useRouter() + const { appInfo, token, signOut, signedIn, user } = useGlobal() -const { projectLoadedHook, project, isSharedBase, loadProjectMetaInfo, projectMetaInfo, saveTheme } = useProject() +const { + project, + isSharedBase, + loadProjectMetaInfo, + projectMetaInfo, + saveTheme, + isLoading: isLoadingProject, + loadProject, + reset, +} = useProject() const { clearTabs, addTab } = useTabs() @@ -114,7 +128,7 @@ const copyProjectInfo = async () => { // Copied to clipboard message.info(t('msg.info.copiedToClipboard')) } catch (e: any) { - console.log(e) + console.error(e) message.error(e.message) } } @@ -125,7 +139,7 @@ const copyAuthToken = async () => { // Copied to clipboard message.info(t('msg.info.copiedToClipboard')) } catch (e: any) { - console.log(e) + console.error(e) message.error(e.message) } } @@ -140,11 +154,23 @@ onKeyStroke( clearTabs() -projectLoadedHook(() => { +onBeforeMount(async () => { + if (!isLoadingProject.value) { + await loadProject() + } + if (!route.params.type && isUIAllowed('teamAndAuth')) { addTab({ type: TabType.AUTH, title: t('title.teamAndAuth') }) } + + /** If v1 url found navigate to corresponding new url */ + const { type, name, view } = route.query + if (type && name) { + await router.replace(`/nc/${route.params.projectId}/${type}/${name}${view ? `/${view}` : ''}`) + } }) + +onBeforeUnmount(reset)