|
|
@ -1,7 +1,6 @@ |
|
|
|
<script lang="ts" setup> |
|
|
|
<script lang="ts" setup> |
|
|
|
import { Empty, Modal, message } from 'ant-design-vue' |
|
|
|
import { Empty, Modal, message } from 'ant-design-vue' |
|
|
|
import type { ProjectType } from 'nocodb-sdk' |
|
|
|
import type { ProjectType } from 'nocodb-sdk' |
|
|
|
import { Chrome } from '@ckpack/vue-color' |
|
|
|
|
|
|
|
import tinycolor from 'tinycolor2' |
|
|
|
import tinycolor from 'tinycolor2' |
|
|
|
import { |
|
|
|
import { |
|
|
|
computed, |
|
|
|
computed, |
|
|
@ -68,50 +67,41 @@ const deleteProject = (project: ProjectType) => { |
|
|
|
|
|
|
|
|
|
|
|
await loadProjects() |
|
|
|
await loadProjects() |
|
|
|
|
|
|
|
|
|
|
|
const themePrimaryColors = $ref( |
|
|
|
const handleProjectColor = async (projectId: string, color: string) => { |
|
|
|
(() => { |
|
|
|
const tcolor = tinycolor(color) |
|
|
|
const colors: Record<string, any> = {} |
|
|
|
if (tcolor.isValid()) { |
|
|
|
for (const project of projects?.value || []) { |
|
|
|
const complement = tcolor.complement() |
|
|
|
if (project?.id) { |
|
|
|
const project: ProjectType = await $api.project.read(projectId) |
|
|
|
try { |
|
|
|
const meta = project?.meta && typeof project.meta === 'string' ? JSON.parse(project.meta) : project.meta || {} |
|
|
|
const projectMeta = typeof project.meta === 'string' ? JSON.parse(project.meta) : project.meta |
|
|
|
await $api.project.update(projectId, { |
|
|
|
colors[project.id] = tinycolor(projectMeta?.theme?.primaryColor).isValid() |
|
|
|
color, |
|
|
|
? projectMeta?.theme?.primaryColor |
|
|
|
meta: JSON.stringify({ |
|
|
|
: themeV2Colors['royal-blue'].DEFAULT |
|
|
|
...meta, |
|
|
|
} catch (e) { |
|
|
|
theme: { |
|
|
|
colors[project.id] = themeV2Colors['royal-blue'].DEFAULT |
|
|
|
primaryColor: color, |
|
|
|
} |
|
|
|
accentColor: complement.toHex8String(), |
|
|
|
} |
|
|
|
}, |
|
|
|
} |
|
|
|
}), |
|
|
|
return colors |
|
|
|
}) |
|
|
|
})(), |
|
|
|
// Update local project |
|
|
|
) |
|
|
|
const localProject = projects.value?.find((p) => p.id === projectId) |
|
|
|
|
|
|
|
if (localProject) { |
|
|
|
const oldPrimaryColors = ref({ ...themePrimaryColors }) |
|
|
|
localProject.color = color |
|
|
|
|
|
|
|
localProject.meta = JSON.stringify({ |
|
|
|
watch(themePrimaryColors, async (nextColors) => { |
|
|
|
...meta, |
|
|
|
for (const [projectId, nextColor] of Object.entries(nextColors)) { |
|
|
|
theme: { |
|
|
|
if (oldPrimaryColors.value[projectId] === nextColor) continue |
|
|
|
primaryColor: color, |
|
|
|
const hexColor = nextColor.hex8 ? nextColor.hex8 : nextColor |
|
|
|
accentColor: complement.toHex8String(), |
|
|
|
const tcolor = tinycolor(hexColor) |
|
|
|
}, |
|
|
|
if (tcolor) { |
|
|
|
|
|
|
|
const complement = tcolor.complement() |
|
|
|
|
|
|
|
const project: ProjectType = await $api.project.read(projectId) |
|
|
|
|
|
|
|
const meta = project?.meta && typeof project.meta === 'string' ? JSON.parse(project.meta) : project.meta || {} |
|
|
|
|
|
|
|
await $api.project.update(projectId, { |
|
|
|
|
|
|
|
color: hexColor, |
|
|
|
|
|
|
|
meta: JSON.stringify({ |
|
|
|
|
|
|
|
...meta, |
|
|
|
|
|
|
|
theme: { |
|
|
|
|
|
|
|
primaryColor: hexColor, |
|
|
|
|
|
|
|
accentColor: complement.toHex8String(), |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
}), |
|
|
|
|
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
oldPrimaryColors.value = { ...themePrimaryColors } |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
const getProjectPrimary = (project: ProjectType) => { |
|
|
|
|
|
|
|
const meta = project?.meta && typeof project.meta === 'string' ? JSON.parse(project.meta) : project.meta || {} |
|
|
|
|
|
|
|
return meta?.theme?.primaryColor || themeV2Colors['royal-blue'].DEFAULT |
|
|
|
|
|
|
|
} |
|
|
|
</script> |
|
|
|
</script> |
|
|
|
|
|
|
|
|
|
|
|
<template> |
|
|
|
<template> |
|
|
@ -219,7 +209,7 @@ watch(themePrimaryColors, async (nextColors) => { |
|
|
|
<div |
|
|
|
<div |
|
|
|
class="color-selector" |
|
|
|
class="color-selector" |
|
|
|
:style="{ |
|
|
|
:style="{ |
|
|
|
'background-color': themePrimaryColors[record.id].hex8 || themePrimaryColors[record.id], |
|
|
|
'background-color': getProjectPrimary(record), |
|
|
|
'width': '8px', |
|
|
|
'width': '8px', |
|
|
|
'height': '100%', |
|
|
|
'height': '100%', |
|
|
|
}" |
|
|
|
}" |
|
|
@ -229,10 +219,10 @@ watch(themePrimaryColors, async (nextColors) => { |
|
|
|
<template #expandIcon></template> |
|
|
|
<template #expandIcon></template> |
|
|
|
|
|
|
|
|
|
|
|
<GeneralColorPicker |
|
|
|
<GeneralColorPicker |
|
|
|
v-model="themePrimaryColors[record.id]" |
|
|
|
|
|
|
|
:colors="projectThemeColors" |
|
|
|
:colors="projectThemeColors" |
|
|
|
:row-size="9" |
|
|
|
:row-size="9" |
|
|
|
:advanced="false" |
|
|
|
:advanced="false" |
|
|
|
|
|
|
|
@input="handleProjectColor(record.id, $event)" |
|
|
|
/> |
|
|
|
/> |
|
|
|
<a-sub-menu key="pick-primary"> |
|
|
|
<a-sub-menu key="pick-primary"> |
|
|
|
<template #title> |
|
|
|
<template #title> |
|
|
@ -242,7 +232,7 @@ watch(themePrimaryColors, async (nextColors) => { |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
<template #expandIcon></template> |
|
|
|
<template #expandIcon></template> |
|
|
|
<Chrome v-model="themePrimaryColors[record.id]" /> |
|
|
|
<GeneralChromeWrapper @input="handleProjectColor(record.id, $event)" /> |
|
|
|
</a-sub-menu> |
|
|
|
</a-sub-menu> |
|
|
|
</a-sub-menu> |
|
|
|
</a-sub-menu> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|