多维表格
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.
 
 
 
 
 
 

272 lines
11 KiB

<script setup lang="ts">
import { ViewLockType } from 'nocodb-sdk'
const { t } = useI18n()
const { isMobileMode, user } = useGlobal()
const { activeView, openedViewsTab } = storeToRefs(useViewsStore())
const { basesUser } = storeToRefs(useBases())
const { base, isSharedBase } = storeToRefs(useBase())
const { activeTable } = storeToRefs(useTablesStore())
const { isLeftSidebarOpen } = storeToRefs(useSidebarStore())
const isViewOwner = computed(() => {
return activeView.value?.owned_by === user.value?.id
})
const idUserMap = computed(() => {
return (basesUser.value.get(base.value?.id) || []).reduce((acc, user) => {
acc[user.id] = user
acc[user.email] = user
return acc
}, {} as Record<string, any>)
})
const viewModeInfo = computed(() => {
switch (activeView.value?.lock_type) {
case ViewLockType.Collaborative:
return t(viewLockIcons[ViewLockType.Collaborative]?.title)
case ViewLockType.Personal:
return `${t(viewLockIcons[ViewLockType.Personal]?.title)} ${
isViewOwner.value
? `(${t('general.you')})`
: activeView.value?.owned_by && idUserMap.value[activeView.value.owned_by]
? `(${idUserMap.value[activeView.value.owned_by]?.display_name || idUserMap.value[activeView.value.owned_by]?.email})`
: ''
}`
case ViewLockType.Locked:
if (!activeView.value?.meta?.lockedByUserId || idUserMap.value[activeView.value?.meta?.lockedByUserId]) {
return t(viewLockIcons[ViewLockType.Locked]?.title)
}
return t('title.lockedByUser', {
user:
idUserMap.value[activeView.value?.meta?.lockedByUserId]?.id === user.value?.id
? t('general.you')
: idUserMap.value[activeView.value?.meta?.lockedByUserId]?.display_name ||
idUserMap.value[activeView.value?.meta?.lockedByUserId]?.email,
})
default:
return t(viewLockIcons[ViewLockType.Collaborative]?.title)
}
})
</script>
<template>
<div
class="flex flex-row items-center border-gray-50 transition-all duration-100 select-none"
:class="{
'text-base w-[calc(100%_-_52px)]': isMobileMode,
'w-[calc(100%_-_44px)]': !isMobileMode && !isLeftSidebarOpen,
'w-full': !isMobileMode && isLeftSidebarOpen,
}"
>
<template v-if="!isMobileMode">
<SmartsheetTopbarProjectListDropdown v-if="activeTable">
<template #default="{ isOpen }">
<div
class="rounded-lg h-8 px-2 text-gray-700 font-weight-500 hover:(bg-gray-100 text-gray-900) flex items-center gap-1 cursor-pointer max-w-1/3"
:class="{
'!max-w-none': isSharedBase && !isMobileMode,
'': !isMobileMode && isLeftSidebarOpen,
}"
>
<NcTooltip :disabled="isSharedBase || isOpen">
<template #title>
<span class="capitalize">
{{ base?.title }}
</span>
</template>
<GeneralProjectIcon :type="base?.type" :color="parseProp(base.meta).iconColor" class="!grayscale min-w-4" />
</NcTooltip>
<template v-if="isSharedBase">
<NcTooltip
class="ml-1 truncate nc-active-base-title max-w-full !leading-5"
show-on-truncate-only
:disabled="isOpen"
>
<template #title>
<span class="capitalize">
{{ base?.title }}
</span>
</template>
<span
class="text-ellipsis capitalize"
:style="{
wordBreak: 'keep-all',
whiteSpace: 'nowrap',
display: 'inline',
}"
>
{{ base?.title }}
</span>
</NcTooltip>
<GeneralIcon
icon="chevronDown"
class="!text-current opacity-70 flex-none transform transition-transform duration-25 w-3.5 h-3.5"
:class="{ '!rotate-180': isOpen }"
/>
</template>
</div>
</template>
</SmartsheetTopbarProjectListDropdown>
<GeneralIcon icon="ncSlash1" class="nc-breadcrumb-divider" />
</template>
<template v-if="!(isMobileMode && !activeView?.is_default)">
<SmartsheetTopbarTableListDropdown v-if="activeTable">
<template #default="{ isOpen }">
<div
class="rounded-lg h-8 px-2 text-gray-700 font-weight-500 hover:(bg-gray-100 text-gray-900) flex items-center gap-1 cursor-pointer"
:class="{
'max-w-full': isMobileMode,
'max-w-1/2': activeView?.is_default,
'max-w-1/4': !isSharedBase && !isMobileMode && !activeView?.is_default,
'max-w-none': isSharedBase && !isMobileMode,
}"
>
<LazyGeneralEmojiPicker v-if="isMobileMode" :emoji="activeTable?.meta?.icon" readonly size="xsmall" class="mr-1">
<template #default>
<GeneralIcon
icon="table"
class="min-w-5"
:class="{
'!text-gray-500': !isMobileMode,
'!text-gray-700': isMobileMode,
}"
/>
</template>
</LazyGeneralEmojiPicker>
<NcTooltip class="truncate nc-active-table-title max-w-full !leading-5" show-on-truncate-only :disabled="isOpen">
<template #title>
{{ activeTable?.title }}
</template>
<span
class="text-ellipsis"
:style="{
wordBreak: 'keep-all',
whiteSpace: 'nowrap',
display: 'inline',
}"
>
{{ activeTable?.title }}
</span>
</NcTooltip>
<GeneralIcon
icon="chevronDown"
class="!text-current opacity-70 flex-none transform transition-transform duration-25 w-3.5 h-3.5"
:class="{ '!rotate-180': isOpen }"
/>
</div>
</template>
</SmartsheetTopbarTableListDropdown>
</template>
<GeneralIcon v-if="!isMobileMode" icon="ncSlash1" class="nc-breadcrumb-divider" />
<template v-if="!(isMobileMode && activeView?.is_default)">
<!-- <SmartsheetToolbarOpenedViewAction /> -->
<SmartsheetTopbarViewListDropdown>
<template #default="{ isOpen }">
<NcTooltip
:tooltip-style="{ width: '240px', zIndex: '1049' }"
:overlay-inner-style="{ width: '240px' }"
trigger="hover"
placement="bottom"
class="flex"
:disabled="isOpen"
:class="{
'max-w-full': isMobileMode,
'max-w-2/5': !isSharedBase && !isMobileMode && activeView?.is_default,
'max-w-1/2': !isSharedBase && !isMobileMode && !activeView?.is_default,
'max-w-none': isSharedBase && !isMobileMode,
}"
>
<template #title>
<div class="flex flex-col gap-3">
<div>
<div class="text-[10px] leading-[14px] text-gray-300 uppercase mb-1">{{ $t('labels.viewName') }}</div>
<div class="text-small leading-[18px]">
{{ activeView?.is_default ? $t('title.defaultView') : activeView?.title }}
</div>
</div>
<div v-if="activeView?.created_by && idUserMap[activeView?.created_by]">
<div class="text-[10px] leading-[14px] text-gray-300 uppercase mb-1">{{ $t('labels.createdBy') }}</div>
<div class="text-xs">
{{
idUserMap[activeView?.created_by]?.id === user?.id
? $t('general.you')
: idUserMap[activeView?.created_by]?.display_name || idUserMap[activeView?.created_by]?.email
}}
</div>
</div>
<div>
<div class="text-[10px] leading-[14px] text-gray-300 uppercase mb-1">{{ $t('labels.viewMode') }}</div>
<div class="text-xs flex items-start gap-2">
{{ viewModeInfo }}
</div>
</div>
</div>
</template>
<div
class="rounded-lg h-8 px-2 text-gray-800 font-semibold hover:(bg-gray-100 text-gray-900) flex items-center gap-1 cursor-pointer"
:class="{
'max-w-full': !isSharedBase || isMobileMode,
'max-w-none': isSharedBase && !isMobileMode,
}"
>
<LazyGeneralEmojiPicker v-if="isMobileMode" :emoji="activeView?.meta?.icon" readonly size="xsmall" class="mr-1">
<template #default>
<GeneralViewIcon :meta="{ type: activeView?.type }" class="min-w-4.5 text-lg flex" />
</template>
</LazyGeneralEmojiPicker>
<NcTooltip class="truncate nc-active-view-title max-w-full !leading-5" show-on-truncate-only disabled>
<template #title>
{{ activeView?.is_default ? $t('title.defaultView') : activeView?.title }}
</template>
<span
class="text-ellipsis"
:style="{
wordBreak: 'keep-all',
whiteSpace: 'nowrap',
display: 'inline',
}"
>
{{ activeView?.is_default ? $t('title.defaultView') : activeView?.title }}
</span>
</NcTooltip>
<component
:is="viewLockIcons[activeView.lock_type].icon"
v-if="[ViewLockType.Locked, ViewLockType.Personal].includes(activeView?.lock_type)"
class="flex-none w-3.5 h-3.5 mx-0.5"
:class="{
'text-brand-400': activeView?.lock_type === ViewLockType.Personal && isViewOwner,
'text-gray-400': !(activeView?.lock_type === ViewLockType.Personal && isViewOwner),
}"
/>
<GeneralIcon
icon="chevronDown"
class="!text-current opacity-70 flex-none transform transition-transform duration-25 w-3.5 h-3.5"
:class="{ '!rotate-180': isOpen }"
/>
</div>
</NcTooltip>
</template>
</SmartsheetTopbarViewListDropdown>
<LazySmartsheetToolbarReload v-if="openedViewsTab === 'view' && !isMobileMode" />
</template>
</div>
</template>