mirror of
https://github.com/nocodb/nocodb.git
synced 2026-05-04 10:16:40 +00:00
feat: Improved UI (#6222)
* feat: Improved ui (#6156) * refactor: revert Signed-off-by: Pranav C <pranavxc@gmail.com> feat: shared base Signed-off-by: Pranav C <pranavxc@gmail.com> fix: remove duplicate import statement Signed-off-by: Pranav C <pranavxc@gmail.com> fix: disable starred & license menu Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: fix airtable wait issue Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: enable mysql in ci Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: fix checkbox order for sqlite Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: disable quick tests Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: fix dbType env variable for CI Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: workspace API access error fix Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: enable SQLite CI CD Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: use DB_TYPE env variable Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: enable SQLite UT Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: isHub cleanup Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: add check for EE Timezone spec Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> chore: cleanup Signed-off-by: Pranav C <pranavxc@gmail.com> chore: cleanup Signed-off-by: Pranav C <pranavxc@gmail.com> test: EE check fix Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> chore: test correction Signed-off-by: Pranav C <pranavxc@gmail.com> chore: sync latest changes Signed-off-by: Pranav C <pranavxc@gmail.com> test: set EE=false Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> test: set NC Edition to community in workflow file Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> chore: update sdk build command Signed-off-by: Pranav C <pranavxc@gmail.com> refactor: i18n and other changes Signed-off-by: Pranav C <pranavxc@gmail.com> feat: new ui Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: sync tests Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: lint Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: shared view/base related bugs Signed-off-by: Pranav C <pranavxc@gmail.com> * test: checkbox verification sort order fix Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: fix sqlite reset Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: enable selfhosted runners Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * docs: table ops (draft) Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * Docs: screenshots for table-operations.md * refactor: introduce missing buttons Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: get all fields Signed-off-by: Pranav C <pranavxc@gmail.com> * test: UT fix- new data API response Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: EE is false Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: webhook lookup as string in CE Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * fix: include created_at and updated_at Signed-off-by: Pranav C <pranavxc@gmail.com> * test: fix UT newDataAPI response for PG Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * fix: separate api for webhook related plugins Signed-off-by: Pranav C <pranavxc@gmail.com> * test: msyql filter corrections Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: mysql group by test corrections Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: fix datatype for rating field in groupby spec for pg Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: kanban datatype correction Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: column edit for mysql- rating field Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: misc fixes Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: enable 4 workers Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: enable 2 workers per shard only Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * docs: table CRUD * Rename table-operations.md to table-crud.md * Create column-crud.md * docs: row CRUD * Rename row.md to row-crud.md * docs: project crud * docs: toolbar (skeleton) * refactor: single page UI and bug fixes Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: sync tests playwright Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: add missing dependency Signed-off-by: Pranav C <pranavxc@gmail.com> * feat: single page ui, test corrections Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: tests Signed-off-by: Pranav C <pranavxc@gmail.com> * test: project rename test correction Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: remove only Signed-off-by: Pranav C <pranavxc@gmail.com> * test: remove wrong import statement Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: delete option not visible in project context menu Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: move ws access within isEE() Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: fix groupby * test: groupby fix Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * docs: signup & landing page * docs: project crud * docs: project-crud misc * docs: toolbar fields * docs: toolbar / filters * docs: toolbar / group by * docs: toolbar / sort * docs: toolbar / row height * docs: filters additional options * docs: file re-order Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * docs: add links to column types * docs: code snippets * docs: links * docs: lookup * docs: rollup * docs: formula * docs: primary key * docs: display value * docs: development setup * docs: swagger * fix(nc-gui): encodeURIComponent for row id - closes: #6202 * docs: language * docs: expanded record * docs: import airtable * docs: airtable * docs: webhook * docs: revert file rename Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * docs: account settings * docs: audit * docs: meta management * docs: project settings * docs: shared base * docs: shared view * docs: meta sync * docs: team-auth * docs: views * docs: fix URL * docs: URL corrections * fix: shared base, view related bugs Signed-off-by: Pranav C <pranavxc@gmail.com> * test: EE check for WSaccess Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * test: exclude EE tests Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * fix: missing project delete closes #6215 Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: merge existing project meta if found closes #6216 Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: merge existing project meta if found closes #6216 Signed-off-by: Pranav C <pranavxc@gmail.com> --------- Signed-off-by: Pranav C <pranavxc@gmail.com> Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> Co-authored-by: Raju Udava <86527202+dstala@users.noreply.github.com> Co-authored-by: DarkPhoenix2704 <anbarasun123@gmail.com> Co-authored-by: Wing-Kam Wong <wingkwong.code@gmail.com> * refactor: docs and other bug fixes Signed-off-by: Pranav C <pranavxc@gmail.com> * feat: populate default project on super admin signup Signed-off-by: Pranav C <pranavxc@gmail.com> * fix: include created project details in signup response if avail, missing Dockerfile Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: use custom function for resolving ts path aliases Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: add missing generate script Signed-off-by: Pranav C <pranavxc@gmail.com> * chore: webpack build correction - ts path resolve Signed-off-by: Pranav C <pranavxc@gmail.com> --------- Signed-off-by: Pranav C <pranavxc@gmail.com> Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> Co-authored-by: mertmit <mertmit99@gmail.com> Co-authored-by: Raju Udava <86527202+dstala@users.noreply.github.com> Co-authored-by: DarkPhoenix2704 <anbarasun123@gmail.com> Co-authored-by: Wing-Kam Wong <wingkwong.code@gmail.com>
This commit is contained in:
381
packages/nc-gui/components/workspace/Menu.vue
Normal file
381
packages/nc-gui/components/workspace/Menu.vue
Normal file
@@ -0,0 +1,381 @@
|
||||
<script lang="ts" setup>
|
||||
import { storeToRefs } from 'pinia'
|
||||
import type { WorkspaceType } from 'nocodb-sdk'
|
||||
import tinycolor from 'tinycolor2'
|
||||
import { onMounted, projectThemeColors, ref, useWorkspace } from '#imports'
|
||||
import { navigateTo } from '#app'
|
||||
|
||||
const props = defineProps<{
|
||||
isOpen: boolean
|
||||
}>()
|
||||
|
||||
const workspaceStore = useWorkspace()
|
||||
|
||||
const { saveTheme } = workspaceStore
|
||||
const { isWorkspaceOwner } = storeToRefs(workspaceStore)
|
||||
const { loadWorkspaces, clearWorkspaces } = workspaceStore
|
||||
|
||||
const { signOut, signedIn, user, token } = useGlobal()
|
||||
|
||||
const { copy } = useCopy(true)
|
||||
|
||||
const email = computed(() => user.value?.email ?? '---')
|
||||
|
||||
const { isUIAllowed } = useUIPermission()
|
||||
|
||||
const { theme, defaultTheme } = useTheme()
|
||||
|
||||
onMounted(async () => {
|
||||
// await loadWorkspaces()
|
||||
})
|
||||
|
||||
const workspaceModalVisible = ref(false)
|
||||
const isWorkspaceDropdownOpen = ref(false)
|
||||
const isAuthTokenCopied = ref(false)
|
||||
|
||||
const createDlg = ref(false)
|
||||
|
||||
const onWorkspaceCreate = async (workspace: WorkspaceType) => {
|
||||
createDlg.value = false
|
||||
await loadWorkspaces()
|
||||
navigateTo(`/${workspace.id}`)
|
||||
}
|
||||
|
||||
const handleThemeColor = async (mode: 'swatch' | 'primary' | 'accent', color?: string) => {
|
||||
switch (mode) {
|
||||
case 'swatch': {
|
||||
if (color === defaultTheme.primaryColor) {
|
||||
return await saveTheme(defaultTheme)
|
||||
}
|
||||
|
||||
const tcolor = tinycolor(color)
|
||||
if (tcolor.isValid()) {
|
||||
const complement = tcolor.complement()
|
||||
|
||||
await saveTheme({
|
||||
primaryColor: color,
|
||||
accentColor: complement.toHex8String(),
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'primary': {
|
||||
const tcolor = tinycolor(color)
|
||||
|
||||
if (tcolor.isValid()) {
|
||||
await saveTheme({
|
||||
primaryColor: color,
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'accent': {
|
||||
const tcolor = tinycolor(color)
|
||||
|
||||
if (tcolor.isValid()) {
|
||||
await saveTheme({
|
||||
accentColor: color,
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const logout = async () => {
|
||||
await signOut()
|
||||
navigateTo('/signin')
|
||||
}
|
||||
|
||||
const projectStore = useProject()
|
||||
|
||||
const { isSharedBase } = storeToRefs(projectStore)
|
||||
|
||||
// todo: temp
|
||||
const modalVisible = false
|
||||
|
||||
const copyAuthToken = async () => {
|
||||
try {
|
||||
await copy(token.value!)
|
||||
isAuthTokenCopied.value = true
|
||||
} catch (e: any) {
|
||||
console.error(e)
|
||||
message.error(e.message)
|
||||
}
|
||||
}
|
||||
|
||||
onKeyStroke('Escape', () => {
|
||||
if (isWorkspaceDropdownOpen.value) {
|
||||
isWorkspaceDropdownOpen.value = false
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex-grow min-w-20">
|
||||
<a-dropdown
|
||||
v-model:visible="isWorkspaceDropdownOpen"
|
||||
class="h-full min-w-0 flex-1"
|
||||
:trigger="['click']"
|
||||
placement="bottom"
|
||||
overlay-class-name="nc-dropdown-workspace-menu"
|
||||
>
|
||||
<div
|
||||
:style="{ width: props.isOpen ? 'calc(100% - 40px) pr-2' : '100%' }"
|
||||
:class="[props.isOpen ? '' : 'justify-center']"
|
||||
data-testid="nc-workspace-menu"
|
||||
class="group cursor-pointer flex gap-1 items-center nc-workspace-menu overflow-hidden py-1.25 pr-0.25"
|
||||
>
|
||||
<slot name="brandIcon" />
|
||||
<template v-if="props.isOpen">
|
||||
Nocodb
|
||||
<div class="flex flex-grow"></div>
|
||||
<MdiCodeTags class="min-w-[17px] text-md transform rotate-90" />
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<MdiFolder class="text-primary cursor-pointer transform hover:scale-105 text-2xl" />
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<template #overlay>
|
||||
<a-menu class="" @click="isWorkspaceDropdownOpen = false">
|
||||
<a-menu-item-group class="!border-t-0">
|
||||
<a-menu-divider />
|
||||
|
||||
<template v-if="!isSharedBase">
|
||||
<!-- Copy Auth Token -->
|
||||
<a-menu-item key="copy">
|
||||
<div
|
||||
v-e="['a:navbar:user:copy-auth-token']"
|
||||
class="nc-workspace-menu-item group !gap-x-2"
|
||||
@click.stop="copyAuthToken"
|
||||
>
|
||||
<GeneralIcon v-if="isAuthTokenCopied" icon="check" class="group-hover:text-black" />
|
||||
<GeneralIcon v-else icon="copy" class="group-hover:text-black" />
|
||||
<div v-if="isAuthTokenCopied">
|
||||
{{ $t('activity.account.authTokenCopied') }}
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ $t('activity.account.authToken') }}
|
||||
</div>
|
||||
</div>
|
||||
</a-menu-item>
|
||||
|
||||
<a-menu-divider v-if="false" />
|
||||
|
||||
<!-- Theme -->
|
||||
<template v-if="isUIAllowed('projectTheme') && false">
|
||||
<a-sub-menu key="theme">
|
||||
<template #title>
|
||||
<div class="nc-workspace-menu-item group">
|
||||
<GeneralIcon icon="image" class="group-hover:text-accent" />
|
||||
{{ $t('activity.account.themes') }}
|
||||
|
||||
<div class="flex-1" />
|
||||
|
||||
<MaterialSymbolsChevronRightRounded
|
||||
class="transform group-hover:(scale-115 text-accent) text-xl text-gray-400"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #expandIcon></template>
|
||||
|
||||
<LazyGeneralColorPicker
|
||||
:model-value="theme.primaryColor"
|
||||
:colors="projectThemeColors"
|
||||
:row-size="9"
|
||||
:advanced="false"
|
||||
class="rounded-t"
|
||||
@input="handleThemeColor('swatch', $event)"
|
||||
/>
|
||||
|
||||
<!-- Custom Theme -->
|
||||
<a-sub-menu key="theme-2">
|
||||
<template #title>
|
||||
<div class="nc-workspace-menu-item group">
|
||||
{{ $t('labels.customTheme') }}
|
||||
|
||||
<div class="flex-1" />
|
||||
|
||||
<MaterialSymbolsChevronRightRounded
|
||||
class="transform group-hover:(scale-115 text-accent) text-xl text-gray-400"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Primary Color -->
|
||||
<template #expandIcon></template>
|
||||
|
||||
<a-sub-menu key="pick-primary">
|
||||
<template #title>
|
||||
<div class="nc-workspace-menu-item group">
|
||||
<ClarityColorPickerSolid class="group-hover:text-black" />
|
||||
{{ $t('labels.primaryColor') }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #expandIcon></template>
|
||||
|
||||
<LazyGeneralChromeWrapper @input="handleThemeColor('primary', $event)" />
|
||||
</a-sub-menu>
|
||||
|
||||
<!-- Accent Color -->
|
||||
<a-sub-menu key="pick-accent">
|
||||
<template #title>
|
||||
<div class="nc-workspace-menu-item group">
|
||||
<ClarityColorPickerSolid class="group-hover:text-black" />
|
||||
{{ $t('labels.accentColor') }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #expandIcon></template>
|
||||
|
||||
<LazyGeneralChromeWrapper @input="handleThemeColor('accent', $event)" />
|
||||
</a-sub-menu>
|
||||
</a-sub-menu>
|
||||
</a-sub-menu>
|
||||
</template>
|
||||
|
||||
<a-menu-divider v-if="false" />
|
||||
|
||||
<!-- Preview As -->
|
||||
<a-sub-menu v-if="isUIAllowed('previewAs') && false" key="preview-as">
|
||||
<template #title>
|
||||
<div v-e="['c:navdraw:preview-as']" class="nc-workspace-menu-item group">
|
||||
<GeneralIcon icon="preview" class="group-hover:text-black" />
|
||||
{{ $t('activity.previewAs') }}
|
||||
|
||||
<div class="flex-1" />
|
||||
|
||||
<MaterialSymbolsChevronRightRounded
|
||||
class="transform group-hover:(scale-115 text-accent) text-xl text-gray-400"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #expandIcon></template>
|
||||
|
||||
<LazyGeneralPreviewAs />
|
||||
</a-sub-menu>
|
||||
</template>
|
||||
<!-- Language -->
|
||||
<a-sub-menu
|
||||
v-if="!isEeUI"
|
||||
key="language"
|
||||
class="lang-menu !py-0"
|
||||
popup-class-name="scrollbar-thin-dull min-w-50 max-h-90vh !overflow-auto"
|
||||
>
|
||||
<template #title>
|
||||
<div class="nc-workspace-menu-item group">
|
||||
<GeneralIcon icon="translate" class="group-hover:text-black nc-language mr-0.1" />
|
||||
{{ $t('labels.language') }}
|
||||
<div class="flex items-center text-gray-400 text-xs">(Community Translated)</div>
|
||||
<div class="flex-1" />
|
||||
|
||||
<MaterialSymbolsChevronRightRounded
|
||||
class="transform group-hover:(scale-115 text-accent) text-xl text-gray-400"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #expandIcon></template>
|
||||
|
||||
<LazyGeneralLanguageMenu />
|
||||
</a-sub-menu>
|
||||
|
||||
<!-- Account -->
|
||||
<template v-if="signedIn && !isSharedBase">
|
||||
<a-sub-menu key="account">
|
||||
<template #title>
|
||||
<div class="nc-workspace-menu-item group">
|
||||
<GeneralIcon icon="account" class="group-hover:text-accent" />
|
||||
{{ $t('labels.account') }}
|
||||
<div class="flex-1" />
|
||||
|
||||
<MaterialSymbolsChevronRightRounded
|
||||
class="transform group-hover:(scale-115 text-accent) text-xl text-gray-400"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #expandIcon></template>
|
||||
|
||||
<a-menu-item key="0" class="!rounded-t">
|
||||
<nuxt-link v-e="['c:navbar:user:email']" class="nc-workspace-menu-item group !no-underline" to="/account/users">
|
||||
<GeneralIcon icon="at" class="mt-1 group-hover:text-accent" />
|
||||
<div class="prose-sm group-hover:text-primary">
|
||||
<div>Account</div>
|
||||
<div class="text-xs text-gray-500">{{ email }}</div>
|
||||
</div>
|
||||
</nuxt-link>
|
||||
</a-menu-item>
|
||||
|
||||
<a-menu-item key="1" class="!rounded-b">
|
||||
<div v-e="['a:navbar:user:sign-out']" class="nc-workspace-menu-item group" @click="logout">
|
||||
<GeneralIcon icon="signout" class="group-hover:(!text-accent)" />
|
||||
|
||||
<span class="prose-sm nc-user-menu-signout">
|
||||
{{ $t('general.signOut') }}
|
||||
</span>
|
||||
</div>
|
||||
</a-menu-item>
|
||||
</a-sub-menu>
|
||||
</template>
|
||||
</a-menu-item-group>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
<GeneralModal v-model:visible="workspaceModalVisible" :class="{ active: modalVisible }" width="80%" :footer="null">
|
||||
<div class="relative flex flex-col px-6 py-2">
|
||||
<div class="absolute right-4 top-4 z-20">
|
||||
<a-button type="text" class="!p-1 !h-7 !rounded" @click="workspaceModalVisible = false">
|
||||
<component :is="iconMap.close" />
|
||||
</a-button>
|
||||
</div>
|
||||
<a-tabs v-model:activeKey="tab">
|
||||
<template v-if="isWorkspaceOwner">
|
||||
<a-tab-pane key="collab" tab="Collaborators" class="w-full">
|
||||
<WorkspaceCollaboratorsList class="h-full" />
|
||||
</a-tab-pane>
|
||||
<!-- <a-tab-pane key="settings" tab="Settings" class="w-full">
|
||||
<div class="min-h-50 flex items-center justify-center">Not available</div>
|
||||
</a-tab-pane> -->
|
||||
</template>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</GeneralModal>
|
||||
|
||||
<WorkspaceCreateDlg v-model="createDlg" @success="onWorkspaceCreate" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.nc-workspace-title-input {
|
||||
@apply flex-grow py-2 px-3 outline-none hover:(bg-gray-50) focus:(bg-gray-50) font-medium rounded text-md text-defaault;
|
||||
}
|
||||
|
||||
.nc-menu-sub-head {
|
||||
@apply pt-2 pb-2 text-gray-500 text-sm px-5;
|
||||
}
|
||||
|
||||
.nc-workspace-menu-item {
|
||||
@apply flex items-center pl-2 py-2 gap-2 text-sm hover:text-black;
|
||||
}
|
||||
|
||||
:deep(.ant-dropdown-menu-item-group-title) {
|
||||
@apply hidden;
|
||||
}
|
||||
|
||||
:deep(.ant-tabs-nav) {
|
||||
@apply !mb-0;
|
||||
}
|
||||
|
||||
:deep(.ant-dropdown-menu-submenu-title) {
|
||||
@apply !py-0;
|
||||
.nc-icon {
|
||||
@apply !text-xs;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user