Browse Source

fix: use injection for useProject

Signed-off-by: mertmit <mertmit99@gmail.com>
pull/3390/head
mertmit 2 years ago
parent
commit
71ecbe1819
  1. 22
      packages/nc-gui-v2/composables/useInjectionState/index.ts
  2. 90
      packages/nc-gui-v2/composables/useProject.ts
  3. 4
      packages/nc-gui-v2/pages/index/index/[projectId].vue

22
packages/nc-gui-v2/composables/useInjectionState/index.ts

@ -1,20 +1,36 @@
import type { InjectionKey } from 'vue'
import type { EffectScope, InjectionKey } from 'vue'
import { getCurrentScope } from 'vue'
type ExtendedScope<T> = { [key: symbol]: T } & EffectScope
export function useInjectionState<Arguments extends any[], Return>(
composable: (...args: Arguments) => Return,
keyName = 'InjectionState',
): readonly [useInjectionState: (...args: Arguments) => Return, useInjectedState: () => Return | undefined] {
const key: string | InjectionKey<Return> = Symbol(keyName)
const keySymbol = Symbol(keyName)
const key: string | InjectionKey<Return> = keySymbol
const useProvidingState = (...args: Arguments) => {
const providedState = composable(...args)
const currentScope = getCurrentScope() as ExtendedScope<Return>
currentScope[keySymbol] = providedState
provide(key, providedState)
return providedState
}
const useInjectedState = () => inject(key, undefined)
const useInjectedState = () => {
let injection = inject(key, undefined)
if (typeof injection === 'undefined') {
const currentScope = getCurrentScope() as ExtendedScope<Return>
injection = currentScope[keySymbol]
}
return injection
}
return [useProvidingState, useInjectedState]
}

90
packages/nc-gui-v2/composables/useProject.ts

@ -1,34 +1,25 @@
import type { MaybeRef } from '@vueuse/core'
import { SqlUiFactory } from 'nocodb-sdk'
import type { OracleUi, ProjectType, TableType } from 'nocodb-sdk'
import type { MaybeRef } from '@vueuse/core'
import { useNuxtApp, useRoute, useState } from '#app'
import { useNuxtApp, useRoute } from '#app'
import type { ProjectMetaInfo } from '~/lib'
import { USER_PROJECT_ROLES } from '~/lib'
import type { ThemeConfig } from '@/composables/useTheme'
import { useInjectionState } from '#imports'
export function useProject(projectId?: MaybeRef<string>) {
const projectRoles = useState<Record<string, boolean>>(USER_PROJECT_ROLES, () => ({}))
const [setup, use] = useInjectionState((_projectId?: MaybeRef<string>) => {
const { $api } = useNuxtApp()
let _projectId = $ref('')
const project = useState<ProjectType>('project')
const tables = useState<TableType[]>('tables', () => [] as TableType[])
const route = useRoute()
const { includeM2M } = useGlobal()
const { setTheme } = useTheme()
const projectMetaInfo = useState<ProjectMetaInfo | undefined>('projectMetaInfo')
const projectId = computed(() => (_projectId ? unref(_projectId) : (route.params.projectId as string)))
const project = ref<ProjectType>({})
const tables = ref<TableType[]>([])
const projectRoles = ref<Record<string, boolean>>({})
const projectMetaInfo = ref<ProjectMetaInfo | undefined>()
// todo: refactor path param name and variable name
const projectType = $computed(() => route.params.projectType as string)
const isLoaded = ref(false)
const projectBaseType = $computed(() => project.value?.bases?.[0]?.type || '')
const isMysql = computed(() => ['mysql', 'mysql2'].includes(projectBaseType))
const isMssql = computed(() => projectBaseType === 'mssql')
const isPg = computed(() => projectBaseType === 'pg')
const sqlUi = computed(
() => SqlUiFactory.create({ client: projectBaseType }) as Exclude<ReturnType<typeof SqlUiFactory['create']>, typeof OracleUi>,
)
const isSharedBase = computed(() => projectType === 'base')
const projectMeta = computed(() => {
try {
@ -38,6 +29,17 @@ export function useProject(projectId?: MaybeRef<string>) {
}
})
const projectBaseType = $computed(() => project.value?.bases?.[0]?.type || '')
const sqlUi = computed(
() => SqlUiFactory.create({ client: projectBaseType }) as Exclude<ReturnType<typeof SqlUiFactory['create']>, typeof OracleUi>,
)
const isMysql = computed(() => ['mysql', 'mysql2'].includes(projectBaseType))
const isMssql = computed(() => projectBaseType === 'mssql')
const isPg = computed(() => projectBaseType === 'pg')
const isSharedBase = computed(() => projectType === 'base')
async function loadProjectMetaInfo(force?: boolean) {
if (!projectMetaInfo.value || force) {
const data = await $api.project.metaGet(project.value.id!, {}, {})
@ -74,31 +76,21 @@ export function useProject(projectId?: MaybeRef<string>) {
}
async function loadProject() {
if (unref(projectId)) {
_projectId = unref(projectId)!
} else if (projectType === 'base') {
if (projectType === 'base') {
const baseData = await $api.public.sharedBaseGet(route.params.projectId as string)
_projectId = baseData.project_id!
project.value = await $api.project.read(baseData.project_id!)
} else {
_projectId = route.params.projectId as string
project.value = await $api.project.read(projectId.value)
}
isLoaded.value = true
project.value = await $api.project.read(_projectId!)
await loadProjectRoles()
await loadTables()
setTheme(projectMeta.value?.theme)
}
async function updateProject(data: Partial<ProjectType>) {
if (unref(projectId)) {
_projectId = unref(projectId)!
} else if (projectType === 'base') {
if (projectType === 'base') {
return
} else {
_projectId = route.params.projectId as string
}
await $api.project.update(_projectId, data)
await $api.project.update(projectId.value, data)
}
async function saveTheme(theme: Partial<ThemeConfig>) {
@ -112,14 +104,24 @@ export function useProject(projectId?: MaybeRef<string>) {
setTheme(theme)
}
watch(project, () => {
setTheme(projectMeta.value?.theme || {})
})
watch(
() => route.params,
(v) => {
if (!v?.projectId) {
setTheme({})
}
},
)
onScopeDispose(() => {
if (isLoaded.value === true) {
project.value = {}
tables.value = []
projectMetaInfo.value = undefined
projectRoles.value = {}
setTheme({})
}
})
return {
@ -139,4 +141,16 @@ export function useProject(projectId?: MaybeRef<string>) {
projectMeta,
saveTheme,
}
}, 'useProject')
export const provideProject = setup
export function useProject(projectId?: MaybeRef<string>) {
const state = use()
if (!state) {
return setup(projectId)
}
return state
}

4
packages/nc-gui-v2/pages/index/index/[id].vue → packages/nc-gui-v2/pages/index/index/[projectId].vue

@ -21,7 +21,7 @@ useSidebar({ hasSidebar: false })
const route = useRoute()
const { project, loadProject, updateProject } = useProject(route.params.id as string)
const { project, loadProject, updateProject } = useProject(route.params.projectId as string)
await loadProject()
@ -43,7 +43,7 @@ const renameProject = async () => {
try {
await updateProject(formState)
navigateTo(`/nc/${route.params.id}`)
navigateTo(`/nc/${route.params.projectId}`)
} catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e))
}
Loading…
Cancel
Save