Browse Source

feat: project theme

Signed-off-by: mertmit <mertmit99@gmail.com>
pull/3368/head
mertmit 2 years ago
parent
commit
9505c4c569
  1. 9
      packages/nc-gui-v2/composables/useProject.ts
  2. 52
      packages/nc-gui-v2/composables/useTheme/index.ts
  3. 6
      packages/nc-gui-v2/pages/[projectType]/[projectId]/index.vue
  4. 2
      packages/nocodb/src/lib/meta/api/projectApis.ts

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

@ -88,6 +88,14 @@ export function useProject(projectId?: MaybeRef<string>) {
await $api.project.update(_projectId, data)
}
function getProjectMeta() {
try {
return typeof project.value.meta === 'string' ? JSON.parse(project.value.meta) : project.value.meta
} catch (e) {
return {}
}
}
return {
project,
tables,
@ -102,5 +110,6 @@ export function useProject(projectId?: MaybeRef<string>) {
isSharedBase,
loadProjectMetaInfo,
projectMetaInfo,
getProjectMeta,
}
}

52
packages/nc-gui-v2/composables/useTheme/index.ts

@ -1,7 +1,6 @@
import { ConfigProvider } from 'ant-design-vue'
import type { Theme as AntTheme } from 'ant-design-vue/es/config-provider'
import { useStorage } from '@vueuse/core'
import { NOCO, hexToRGB, themeV2Colors, useCssVar, useInjectionState } from '#imports'
import { hexToRGB, themeV2Colors, useCssVar, useInjectionState, useProject } from '#imports'
interface ThemeConfig extends AntTheme {
primaryColor: string
@ -12,17 +11,40 @@ const [setup, use] = useInjectionState((config?: Partial<ThemeConfig>) => {
const primaryColor = useCssVar('--color-primary', typeof document !== 'undefined' ? document.documentElement : null)
const accentColor = useCssVar('--color-accent', typeof document !== 'undefined' ? document.documentElement : null)
/** current theme config */
const currentTheme = useStorage<ThemeConfig>(
`${NOCO}db-theme`,
{
const { project, getProjectMeta, updateProject } = useProject()
const route = useRoute()
// set theme based on active project
watch(project, () => {
setTheme({
primaryColor: themeV2Colors['royal-blue'].DEFAULT,
accentColor: themeV2Colors.pink['500'],
...getProjectMeta()?.theme,
})
})
// set default theme for routes out of project
watch(
() => route,
(v) => {
if (!v.params?.projectId) {
setTheme({
primaryColor: themeV2Colors['royal-blue'].DEFAULT,
accentColor: themeV2Colors.pink['500'],
})
}
},
localStorage,
{ mergeDefaults: true },
{ deep: true },
)
/** current theme config */
const currentTheme = ref({
primaryColor: themeV2Colors['royal-blue'].DEFAULT,
accentColor: themeV2Colors.pink['500'],
...getProjectMeta()?.theme,
})
/** set initial config */
setTheme(config ?? currentTheme.value)
@ -39,9 +61,23 @@ const [setup, use] = useInjectionState((config?: Partial<ThemeConfig>) => {
})
}
async function saveTheme(theme: Partial<ThemeConfig>) {
const meta = getProjectMeta()
await updateProject({
meta: JSON.stringify({
...meta,
theme: {
...theme,
},
}),
})
setTheme(theme)
}
return {
theme: currentTheme,
setTheme,
saveTheme,
}
}, 'theme')

6
packages/nc-gui-v2/pages/[projectType]/[projectId]/index.vue

@ -59,11 +59,11 @@ let pickerActive = $ref<boolean | 'primary' | 'accent'>(false)
const email = computed(() => user.value?.email ?? '---')
const { setTheme, theme } = useTheme()
const { saveTheme, theme } = useTheme()
watch(pickedColor, (nextColor) => {
if (pickerActive && nextColor.hex) {
setTheme({
saveTheme({
primaryColor: pickerActive === 'primary' ? nextColor.hex : theme.value.primaryColor,
accentColor: pickerActive === 'accent' ? nextColor.hex : theme.value.accentColor,
})
@ -348,7 +348,7 @@ const onMenuClose = (visible: boolean) => {
<a-menu-divider />
<a-sub-menu>
<a-sub-menu v-if="isUIAllowed('projectTheme')">
<template #title>
<div class="nc-project-menu-item group">
<ClarityImageLine class="group-hover:text-accent" />

2
packages/nocodb/src/lib/meta/api/projectApis.ts

@ -54,7 +54,7 @@ export async function projectUpdate(
'meta',
]);
if (await Project.getByTitle(data.title) && project.title !== data.title) {
if (data?.title && project.title !== data.title && await Project.getByTitle(data.title)) {
NcError.badRequest('Project title already in use');
}

Loading…
Cancel
Save