|
|
|
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 type { ThemeConfig } from '@/composables/useTheme'
|
|
|
|
import { createEventHook, useInjectionState } from '#imports'
|
|
|
|
|
|
|
|
const [setup, use] = useInjectionState((_projectId?: MaybeRef<string>) => {
|
|
|
|
const { $api, $e } = useNuxtApp()
|
|
|
|
const route = useRoute()
|
|
|
|
const { includeM2M } = useGlobal()
|
|
|
|
const { setTheme, theme } = useTheme()
|
|
|
|
|
|
|
|
const projectLoadedHook = createEventHook<ProjectType>()
|
|
|
|
|
|
|
|
const projectId = computed(() => (_projectId ? unref(_projectId) : (route.params.projectId as string)))
|
|
|
|
const project = ref<ProjectType>({})
|
|
|
|
const tables = ref<TableType[]>([])
|
|
|
|
const projectRoles = useState<Record<string, boolean>>(USER_PROJECT_ROLES, () => ({}))
|
|
|
|
const projectMetaInfo = ref<ProjectMetaInfo | undefined>()
|
|
|
|
|
|
|
|
// todo: refactor path param name and variable name
|
|
|
|
const projectType = $computed(() => route.params.projectType as string)
|
|
|
|
|
|
|
|
const projectMeta = computed(() => {
|
|
|
|
try {
|
|
|
|
return typeof project.value.meta === 'string' ? JSON.parse(project.value.meta) : project.value.meta
|
|
|
|
} catch (e) {
|
|
|
|
return {}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
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!, {}, {})
|
|
|
|
projectMetaInfo.value = data
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function loadProjectRoles() {
|
|
|
|
projectRoles.value = {}
|
|
|
|
if (isSharedBase.value) {
|
|
|
|
const user = await $api.auth.me(
|
|
|
|
{},
|
|
|
|
{
|
|
|
|
headers: {
|
|
|
|
'xc-shared-base-id': route.params.projectId,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)
|
|
|
|
projectRoles.value = user.roles
|
|
|
|
} else if (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, {
|
|
|
|
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!)
|
|
|
|
} else if (projectId.value) {
|
|
|
|
project.value = await $api.project.read(projectId.value)
|
|
|
|
} else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
await loadProjectRoles()
|
|
|
|
await loadTables()
|
|
|
|
setTheme(projectMeta.value?.theme)
|
|
|
|
|
|
|
|
projectLoadedHook.trigger(project.value)
|
|
|
|
}
|
|
|
|
|
|
|
|
async function updateProject(data: Partial<ProjectType>) {
|
|
|
|
if (projectType === 'base') {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (data.meta && typeof data.meta === 'string') {
|
|
|
|
await $api.project.update(projectId.value, data)
|
|
|
|
} else {
|
|
|
|
await $api.project.update(projectId.value, { ...data, meta: JSON.stringify(data.meta) })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function saveTheme(_theme: Partial<ThemeConfig>) {
|
|
|
|
$e('c:themes:change')
|
|
|
|
|
|
|
|
const fullTheme = {
|
|
|
|
primaryColor: theme.value.primaryColor,
|
|
|
|
accentColor: theme.value.accentColor,
|
|
|
|
..._theme,
|
|
|
|
}
|
|
|
|
|
|
|
|
await updateProject({
|
|
|
|
color: fullTheme.primaryColor,
|
|
|
|
meta: {
|
|
|
|
...projectMeta.value,
|
|
|
|
theme: fullTheme,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
setTheme(fullTheme)
|
|
|
|
}
|
|
|
|
|
|
|
|
watch(
|
|
|
|
() => route.params,
|
|
|
|
(v) => {
|
|
|
|
if (!v?.projectId) {
|
|
|
|
setTheme()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
// TODO useProject should only called inside a project for now this doesn't work
|
|
|
|
onScopeDispose(() => {
|
|
|
|
project.value = {}
|
|
|
|
tables.value = []
|
|
|
|
projectMetaInfo.value = undefined
|
|
|
|
projectRoles.value = {}
|
|
|
|
})
|
|
|
|
|
|
|
|
return {
|
|
|
|
project,
|
|
|
|
tables,
|
|
|
|
loadProjectRoles,
|
|
|
|
loadProject,
|
|
|
|
updateProject,
|
|
|
|
loadTables,
|
|
|
|
isMysql,
|
|
|
|
isMssql,
|
|
|
|
isPg,
|
|
|
|
sqlUi,
|
|
|
|
isSharedBase,
|
|
|
|
loadProjectMetaInfo,
|
|
|
|
projectMetaInfo,
|
|
|
|
projectMeta,
|
|
|
|
saveTheme,
|
|
|
|
projectLoadedHook: projectLoadedHook.on,
|
|
|
|
}
|
|
|
|
}, 'useProject')
|
|
|
|
|
|
|
|
export const provideProject = setup
|
|
|
|
|
|
|
|
export function useProject(projectId?: MaybeRef<string>) {
|
|
|
|
const state = use()
|
|
|
|
|
|
|
|
if (!state) {
|
|
|
|
return setup(projectId)
|
|
|
|
}
|
|
|
|
|
|
|
|
return state
|
|
|
|
}
|