多维表格
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
5.7 KiB

import type { BaseType, OracleUi, ProjectType, TableType } from 'nocodb-sdk'
import { SqlUiFactory } from 'nocodb-sdk'
import { isString } from '@vueuse/core'
import { defineStore } from 'pinia'
import {
ClientType,
computed,
createEventHook,
ref,
useApi,
useGlobal,
useNuxtApp,
useRoles,
useRouter,
useTheme,
} from '#imports'
import type { ProjectMetaInfo, ThemeConfig } from '~/lib'
export const useProject = defineStore('projectStore', () => {
const { $e } = useNuxtApp()
const { api, isLoading } = useApi()
const router = useRouter()
const route = $(router.currentRoute)
const { includeM2M } = useGlobal()
const { setTheme, theme } = useTheme()
const { projectRoles, loadProjectRoles } = useRoles()
const projectLoadedHook = createEventHook<ProjectType>()
const project = ref<ProjectType>({})
const bases = computed<BaseType[]>(() => project.value?.bases || [])
const tables = ref<TableType[]>([])
const projectMetaInfo = ref<ProjectMetaInfo | undefined>()
const lastOpenedViewMap = ref<Record<string, string>>({})
const forcedProjectId = ref<string>()
const projectId = computed(() => forcedProjectId.value || (route.params.projectId as string))
// todo: refactor path param name and variable name
const projectType = $computed(() => route.params.projectType as string)
const projectMeta = computed<Record<string, any>>(() => {
const defaultMeta = {
showNullAndEmptyInFilter: false,
}
try {
return (isString(project.value.meta) ? JSON.parse(project.value.meta) : project.value.meta) ?? defaultMeta
} catch (e) {
return defaultMeta
}
})
const sqlUis = computed(() => {
const temp: Record<string, any> = {}
for (const base of bases.value) {
if (base.id) {
temp[base.id] = SqlUiFactory.create({ client: base.type }) as Exclude<
ReturnType<typeof SqlUiFactory['create']>,
typeof OracleUi
>
}
}
return temp
})
function getBaseType(baseId?: string) {
return bases.value.find((base) => base.id === baseId)?.type || ClientType.MYSQL
}
function isMysql(baseId?: string) {
return ['mysql', ClientType.MYSQL].includes(getBaseType(baseId))
}
function isSqlite(baseId?: string) {
return getBaseType(baseId) === ClientType.SQLITE
}
function isMssql(baseId?: string) {
return getBaseType(baseId) === 'mssql'
}
function isPg(baseId?: string) {
return getBaseType(baseId) === 'pg'
}
function isXcdbBase(baseId?: string) {
return (bases.value.find((base) => base.id === baseId)?.is_meta as boolean) || false
}
const isSharedBase = computed(() => projectType === 'base')
async function loadProjectMetaInfo(force?: boolean) {
if (!projectMetaInfo.value || force) {
projectMetaInfo.value = await api.project.metaGet(project.value.id!, {})
}
}
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.filter((table) => bases.value.find((base) => base.id === table.base_id)?.enabled)
}
}
}
async function loadProject(withTheme = true, forcedId?: string) {
if (forcedId) forcedProjectId.value = forcedId
if (projectType === 'base') {
try {
const baseData = await api.public.sharedBaseGet(route.params.projectId as string)
project.value = await api.project.read(baseData.project_id!)
} catch (e: any) {
if (e?.response?.status === 404) {
return router.push('/error/404')
}
throw e
}
} else if (projectId.value) {
project.value = await api.project.read(projectId.value)
} else {
console.warn('Project id not found')
return
}
await loadProjectRoles(project.value.id || projectId.value, isSharedBase.value, projectId.value)
await loadTables()
if (withTheme) setTheme(projectMeta.value?.theme)
return 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: stringifyProp(data.meta) })
}
}
async function saveTheme(_theme: Partial<ThemeConfig>) {
const fullTheme = {
primaryColor: theme.value.primaryColor,
accentColor: theme.value.accentColor,
..._theme,
}
await updateProject({
color: fullTheme.primaryColor,
meta: {
...projectMeta.value,
theme: fullTheme,
},
})
setTheme(fullTheme)
$e('c:themes:change')
}
async function hasEmptyOrNullFilters() {
return await api.project.hasEmptyOrNullFilters(projectId.value)
}
const reset = () => {
project.value = {}
tables.value = []
projectMetaInfo.value = undefined
projectRoles.value = {}
setTheme()
}
const setProject = (projectVal: ProjectType) => {
project.value = projectVal
}
watch(
() => route.params.projectType,
(n) => {
if (!n) reset()
},
{ immediate: true },
)
return {
project,
bases,
tables,
loadProjectRoles,
loadProject,
updateProject,
loadTables,
isMysql,
isMssql,
isPg,
isSqlite,
sqlUis,
isSharedBase,
loadProjectMetaInfo,
projectMetaInfo,
projectMeta,
saveTheme,
projectLoadedHook: projectLoadedHook.on,
reset,
isLoading,
lastOpenedViewMap,
isXcdbBase,
hasEmptyOrNullFilters,
setProject,
getBaseType,
}
})