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

372 lines
12 KiB

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>
1 year ago
<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 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" />&nbsp;
<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)" />&nbsp;
<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>
</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>