Browse Source

Merge pull request #3114 from nocodb/refactor/gui-v2-column-header-ui

refactor: gui v2 column header UI and nocodb logo
pull/3082/head
navi 2 years ago committed by GitHub
parent
commit
cdd7cc1561
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      packages/nc-gui-v2/components.d.ts
  2. 53
      packages/nc-gui-v2/components/dashboard/TreeView.vue
  3. 2
      packages/nc-gui-v2/components/dashboard/settings/AppStore.vue
  4. 16
      packages/nc-gui-v2/components/smartsheet-column/AdvancedOptions.vue
  5. 4
      packages/nc-gui-v2/components/smartsheet-column/CheckboxOptions.vue
  6. 4
      packages/nc-gui-v2/components/smartsheet-column/CurrencyOptions.vue
  7. 2
      packages/nc-gui-v2/components/smartsheet-column/DateOptions.vue
  8. 2
      packages/nc-gui-v2/components/smartsheet-column/DurationOptions.vue
  9. 26
      packages/nc-gui-v2/components/smartsheet-column/EditOrAdd.vue
  10. 22
      packages/nc-gui-v2/components/smartsheet-column/LinkedToAnotherRecordOptions.vue
  11. 16
      packages/nc-gui-v2/components/smartsheet-column/LookupOptions.vue
  12. 6
      packages/nc-gui-v2/components/smartsheet-column/PercentOptions.vue
  13. 8
      packages/nc-gui-v2/components/smartsheet-column/RatingOptions.vue
  14. 18
      packages/nc-gui-v2/components/smartsheet-column/RollupOptions.vue
  15. 2
      packages/nc-gui-v2/components/smartsheet-column/SpecificDBTypeOptions.vue
  16. 28
      packages/nc-gui-v2/components/smartsheet-header/Cell.vue
  17. 24
      packages/nc-gui-v2/components/smartsheet-header/Menu.vue
  18. 28
      packages/nc-gui-v2/components/smartsheet-header/VirtualCell.vue
  19. 8
      packages/nc-gui-v2/components/smartsheet/Grid.vue
  20. 6
      packages/nc-gui-v2/components/smartsheet/Toolbar.vue
  21. 40
      packages/nc-gui-v2/components/tabs/Auth.vue
  22. 2
      packages/nc-gui-v2/components/tabs/auth/ApiTokenManagement.vue
  23. 2
      packages/nc-gui-v2/components/tabs/auth/UserManagement.vue
  24. 2
      packages/nc-gui-v2/layouts/base.vue
  25. 4
      packages/nc-gui-v2/pages/nc/[projectId]/index.vue
  26. 33
      packages/nc-gui-v2/pages/nc/[projectId]/index/index.vue

5
packages/nc-gui-v2/components.d.ts vendored

@ -110,6 +110,8 @@ declare module '@vue/runtime-core' {
MdiInformation: typeof import('~icons/mdi/information')['default'] MdiInformation: typeof import('~icons/mdi/information')['default']
MdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default'] MdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
MdiKeyStar: typeof import('~icons/mdi/key-star')['default'] MdiKeyStar: typeof import('~icons/mdi/key-star')['default']
MdiLens: typeof import('~icons/mdi/lens')['default']
MdiLense: typeof import('~icons/mdi/lense')['default']
MdiLink: typeof import('~icons/mdi/link')['default'] MdiLink: typeof import('~icons/mdi/link')['default']
MdiLinkVariantRemove: typeof import('~icons/mdi/link-variant-remove')['default'] MdiLinkVariantRemove: typeof import('~icons/mdi/link-variant-remove')['default']
MdiLogout: typeof import('~icons/mdi/logout')['default'] MdiLogout: typeof import('~icons/mdi/logout')['default']
@ -136,6 +138,9 @@ declare module '@vue/runtime-core' {
MdiTrashCan: typeof import('~icons/mdi/trash-can')['default'] MdiTrashCan: typeof import('~icons/mdi/trash-can')['default']
MdiWhatsapp: typeof import('~icons/mdi/whatsapp')['default'] MdiWhatsapp: typeof import('~icons/mdi/whatsapp')['default']
MdiXml: typeof import('~icons/mdi/xml')['default'] MdiXml: typeof import('~icons/mdi/xml')['default']
MdiZomm: typeof import('~icons/mdi/zomm')['default']
MdiZoom: typeof import('~icons/mdi/zoom')['default']
MdiZoomIn: typeof import('~icons/mdi/zoom-in')['default']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
} }

53
packages/nc-gui-v2/components/dashboard/TreeView.vue

@ -1,15 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import type { TableType } from 'nocodb-sdk' import type { TableType } from 'nocodb-sdk'
import Sortable from 'sortablejs' import Sortable from 'sortablejs'
import { Empty } from 'ant-design-vue'
import { useNuxtApp, useRoute } from '#app' import { useNuxtApp, useRoute } from '#app'
import { computed, useProject, useTable, useTabs, watchEffect } from '#imports' import { computed, useProject, useTable, useTabs, watchEffect } from '#imports'
import { TabType } from '~/composables' import { TabType } from '~/composables'
import MdiView from '~icons/mdi/eye-circle-outline' import MdiView from '~icons/mdi/eye-circle-outline'
import MdiTableLarge from '~icons/mdi/table-large' import MdiTableLarge from '~icons/mdi/table-large'
import MdiMenuDown from '~icons/mdi/chevron-down'
import MdiMenuIcon from '~icons/mdi/dots-vertical' import MdiMenuIcon from '~icons/mdi/dots-vertical'
import MdiDrag from '~icons/mdi/drag-vertical' import MdiDrag from '~icons/mdi/drag-vertical'
import MdiPlus from '~icons/mdi/plus-circle-outline'
const { addTab } = useTabs() const { addTab } = useTabs()
@ -28,7 +27,6 @@ const tablesById = $computed<Record<string, TableType>>(() =>
}, {}), }, {}),
) )
const showTableList = ref(true)
const tableCreateDlg = ref(false) const tableCreateDlg = ref(false)
let key = $ref(0) let key = $ref(0)
@ -135,13 +133,15 @@ const activeTable = computed(() => {
<template> <template>
<div class="nc-treeview-container flex flex-col"> <div class="nc-treeview-container flex flex-col">
<div class="px-6 py-[11.75px] border-b-1"> <div class="px-6 py-[8.75px] border-b-1 nc-filter-input">
<a-input-search <div class="flex items-center bg-gray-50 rounded relative">
<a-input
v-model:value="filterQuery" v-model:value="filterQuery"
size="small" class="nc-filter-input !bg-transparent"
class="nc-filter-input"
:placeholder="$t('placeholder.searchProjectTree')" :placeholder="$t('placeholder.searchProjectTree')"
/> />
<MdiSearch class="nc-filter-input-icon text-gray-400 mx-3 absolute right-[-4px] top-[7px]" />
</div>
</div> </div>
<a-dropdown :trigger="['contextmenu']"> <a-dropdown :trigger="['contextmenu']">
@ -149,7 +149,6 @@ const activeTable = computed(() => {
<div <div
style="direction: ltr" style="direction: ltr"
class="py-1 px-3 flex w-full align-center gap-1 cursor-pointer" class="py-1 px-3 flex w-full align-center gap-1 cursor-pointer"
@click="showTableList = !showTableList"
@contextmenu="setMenuContext('main')" @contextmenu="setMenuContext('main')"
> >
<span class="flex-grow text-bold uppercase nc-project-tree text-gray-500 font-weight-bold"> <span class="flex-grow text-bold uppercase nc-project-tree text-gray-500 font-weight-bold">
@ -157,24 +156,9 @@ const activeTable = computed(() => {
<template v-if="tables?.length"> ({{ tables.length }}) </template> <template v-if="tables?.length"> ({{ tables.length }}) </template>
</span> </span>
<MdiPlus
v-t="['c:table:create:navdraw']"
class="transform text-gray-500 hover:(text-pink-500 scale-105) nc-btn-tbl-add"
@click.stop="tableCreateDlg = true"
/>
<MdiMenuDown
class="transition-transform !duration-100 text-gray-500 hover:text-pink-500"
:class="{ 'transform rotate-180': showTableList }"
/>
</div> </div>
<div style="direction: ltr" class="flex-1"> <div style="direction: ltr" class="flex-1">
<div <div v-if="tables.length" class="transition-height duration-200 overflow-hidden">
v-if="tables.length"
class="transition-height duration-200 overflow-hidden"
:class="{ 'h-100': showTableList, 'h-0': !showTableList }"
>
<div :key="key" ref="menuRef" class="border-none sortable-list"> <div :key="key" ref="menuRef" class="border-none sortable-list">
<div <div
v-for="table of tables" v-for="table of tables"
@ -207,7 +191,9 @@ const activeTable = computed(() => {
<template #overlay> <template #overlay>
<a-menu class="cursor-pointer"> <a-menu class="cursor-pointer">
<a-menu-item v-t="" class="!text-xs" @click="showRenameTableDlg(table)"><div>Rename</div></a-menu-item> <a-menu-item v-t="" class="!text-xs" @click="showRenameTableDlg(table)">
<div>Rename</div>
</a-menu-item>
<a-menu-item class="!text-xs" @click="deleteTable(table)"> Delete</a-menu-item> <a-menu-item class="!text-xs" @click="deleteTable(table)"> Delete</a-menu-item>
</a-menu> </a-menu>
@ -217,6 +203,14 @@ const activeTable = computed(() => {
</div> </div>
</div> </div>
</div> </div>
<a-card v-else class="mt-4 mx-4 !bg-gray-50">
<div class="flex flex-col align-center">
<a-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" />
<a-button type="primary" @click.stop="tableCreateDlg = true">{{ $t('tooltip.addTable') }}</a-button>
</div>
</a-card>
</div> </div>
</div> </div>
@ -244,7 +238,7 @@ const activeTable = computed(() => {
</div> </div>
</template> </template>
<style scoped> <style scoped lang="scss">
.nc-treeview-container { .nc-treeview-container {
@apply h-[calc(100vh_-_var(--header-height))]; @apply h-[calc(100vh_-_var(--header-height))];
} }
@ -300,6 +294,7 @@ const activeTable = computed(() => {
.nc-tree-item.active { .nc-tree-item.active {
@apply !text-primary font-weight-bold after:(!opacity-20); @apply !text-primary font-weight-bold after:(!opacity-20);
svg { svg {
@apply !text-primary; @apply !text-primary;
} }
@ -308,4 +303,10 @@ const activeTable = computed(() => {
.nc-tree-item:hover { .nc-tree-item:hover {
@apply !text-grey after:(!opacity-5); @apply !text-grey after:(!opacity-5);
} }
:deep(.nc-filter-input) {
.ant-input {
@apply pr-6 !border-0;
}
}
</style> </style>

2
packages/nc-gui-v2/components/dashboard/settings/AppStore.vue

@ -110,7 +110,7 @@ onMounted(async () => {
<div class="flex ml-0.5">Reset</div> <div class="flex ml-0.5">Reset</div>
</div> </div>
</a-button> </a-button>
<a-button v-else size="small" outlined @click="showInstallPluginModal(app)"> <a-button v-else size="small" outlined type="primary" ghost @click="showInstallPluginModal(app)">
<div class="flex flex-row justify-center items-center caption capitalize nc-app-store-card-install"> <div class="flex flex-row justify-center items-center caption capitalize nc-app-store-card-install">
<MdiPlusIcon /> <MdiPlusIcon />
Install Install

16
packages/nc-gui-v2/components/smartsheet-column/AdvancedOptions.vue

@ -16,13 +16,12 @@ formState.value.au = !!formState.value.au
</script> </script>
<template> <template>
<div class="p-4 border-[2px] radius-1 border-grey w-full"> <div class="p-4 border-[2px] radius-1 border-grey w-full flex flex-col gap-2">
<div class="flex justify-space-between"> <div class="flex justify-space-between">
<a-form-item label="NN"> <a-form-item label="NN">
<a-checkbox <a-checkbox
v-model:checked="formState.rqd" v-model:checked="formState.rqd"
:disabled="formState.pk || !sqlUi.columnEditable(formState)" :disabled="formState.pk || !sqlUi.columnEditable(formState)"
size="small"
class="nc-column-checkbox-NN" class="nc-column-checkbox-NN"
@change="onAlter" @change="onAlter"
/> />
@ -31,7 +30,6 @@ formState.value.au = !!formState.value.au
<a-checkbox <a-checkbox
v-model:checked="formState.pk" v-model:checked="formState.pk"
:disabled="!sqlUi.columnEditable(formState)" :disabled="!sqlUi.columnEditable(formState)"
size="small"
class="nc-column-checkbox-PK" class="nc-column-checkbox-PK"
@change="onAlter" @change="onAlter"
/> />
@ -40,7 +38,6 @@ formState.value.au = !!formState.value.au
<a-checkbox <a-checkbox
v-model:checked="formState.ai" v-model:checked="formState.ai"
:disabled="sqlUi.colPropUNDisabled(formState) || !sqlUi.columnEditable(formState)" :disabled="sqlUi.colPropUNDisabled(formState) || !sqlUi.columnEditable(formState)"
size="small"
class="nc-column-checkbox-AI" class="nc-column-checkbox-AI"
@change="onAlter" @change="onAlter"
/> />
@ -50,18 +47,18 @@ formState.value.au = !!formState.value.au
:disabled="sqlUi.colPropUNDisabled(formState) || !sqlUi.columnEditable(formState)" :disabled="sqlUi.colPropUNDisabled(formState) || !sqlUi.columnEditable(formState)"
@change="onAlter" @change="onAlter"
> >
<a-checkbox v-model:checked="formState.un" size="small" class="nc-column-checkbox-UN" /> <a-checkbox v-model:checked="formState.un" class="nc-column-checkbox-UN" />
</a-form-item> </a-form-item>
<a-form-item <a-form-item
label="AU" label="AU"
:disabled="sqlUi.colPropAuDisabled(formState) || !sqlUi.columnEditable(formState)" :disabled="sqlUi.colPropAuDisabled(formState) || !sqlUi.columnEditable(formState)"
@change="onAlter" @change="onAlter"
> >
<a-checkbox v-model:checked="formState.au" size="small" class="nc-column-checkbox-AU" /> <a-checkbox v-model:checked="formState.au" class="nc-column-checkbox-AU" />
</a-form-item> </a-form-item>
</div> </div>
<a-form-item :label="$t('labels.databaseType')" v-bind="validateInfos.dt"> <a-form-item :label="$t('labels.databaseType')" v-bind="validateInfos.dt">
<a-select v-model:value="formState.dt" size="small" @change="onDataTypeChange"> <a-select v-model:value="formState.dt" @change="onDataTypeChange">
<a-select-option v-for="type in dataTypes" :key="type" :value="type"> <a-select-option v-for="type in dataTypes" :key="type" :value="type">
{{ type }} {{ type }}
</a-select-option> </a-select-option>
@ -71,15 +68,14 @@ formState.value.au = !!formState.value.au
<a-input <a-input
v-model:value="formState.dtxp" v-model:value="formState.dtxp"
:disabled="sqlUi.getDefaultLengthIsDisabled(formState.dt) || !sqlUi.columnEditable(formState)" :disabled="sqlUi.getDefaultLengthIsDisabled(formState.dt) || !sqlUi.columnEditable(formState)"
size="small"
@input="onAlter" @input="onAlter"
/> />
</a-form-item> </a-form-item>
<a-form-item v-if="sqlUi.showScale(formState)" label="Scale"> <a-form-item v-if="sqlUi.showScale(formState)" label="Scale">
<a-input v-model="formState.dtxs" :disabled="!sqlUi.columnEditable(formState)" size="small" @input="onAlter" /> <a-input v-model="formState.dtxs" :disabled="!sqlUi.columnEditable(formState)" @input="onAlter" />
</a-form-item> </a-form-item>
<a-form-item :label="$t('placeholder.defaultValue')"> <a-form-item :label="$t('placeholder.defaultValue')">
<a-textarea v-model:value="formState.cdf" size="small" auto-size @input="onAlter(2, true)" /> <a-textarea v-model:value="formState.cdf" auto-size @input="onAlter(2, true)" />
<span class="text-gray-400 text-xs">{{ sqlUi.getDefaultValueForDatatype(formState.dt) }}</span> <span class="text-gray-400 text-xs">{{ sqlUi.getDefaultValueForDatatype(formState.dt) }}</span>
</a-form-item> </a-form-item>
</div> </div>

4
packages/nc-gui-v2/components/smartsheet-column/CheckboxOptions.vue

@ -73,8 +73,9 @@ watch(
<a-row> <a-row>
<a-col :span="24"> <a-col :span="24">
<a-form-item label="Icon"> <a-form-item label="Icon">
<a-select v-model:value="formState.meta.iconIdx" size="small" class="w-52"> <a-select v-model:value="formState.meta.iconIdx" class="w-52">
<a-select-option v-for="(icon, i) of iconList" :key="i" :value="i"> <a-select-option v-for="(icon, i) of iconList" :key="i" :value="i">
<div class="flex items-center">
<component <component
:is="getMdiIcon(icon.checked)" :is="getMdiIcon(icon.checked)"
class="mx-1" class="mx-1"
@ -88,6 +89,7 @@ watch(
color: formState.meta.color, color: formState.meta.color,
}" }"
/> />
</div>
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>

4
packages/nc-gui-v2/components/smartsheet-column/CurrencyOptions.vue

@ -67,12 +67,11 @@ formState.value.meta = {
</script> </script>
<template> <template>
<a-row> <a-row gutter="8">
<a-col :span="12"> <a-col :span="12">
<a-form-item v-bind="validateInfos['meta.currency_locale']" label="Currency Locale"> <a-form-item v-bind="validateInfos['meta.currency_locale']" label="Currency Locale">
<a-select <a-select
v-model:value="formState.meta.currency_locale" v-model:value="formState.meta.currency_locale"
size="small"
class="w-52" class="w-52"
show-search show-search
:filter-option="filterOption" :filter-option="filterOption"
@ -91,7 +90,6 @@ formState.value.meta = {
class="w-52" class="w-52"
show-search show-search
:filter-option="filterOption" :filter-option="filterOption"
size="small"
:disabled="isMoney && isPg" :disabled="isMoney && isPg"
> >
<a-select-option v-for="(currencyCode, i) of currencyList" :key="i" :value="currencyCode"> <a-select-option v-for="(currencyCode, i) of currencyList" :key="i" :value="currencyCode">

2
packages/nc-gui-v2/components/smartsheet-column/DateOptions.vue

@ -12,7 +12,7 @@ if (!formState.meta?.date_format) {
<template> <template>
<a-form-item label="Date Format"> <a-form-item label="Date Format">
<a-select v-model:value="formState.meta.date_format" size="small"> <a-select v-model:value="formState.meta.date_format">
<a-select-option v-for="(format, i) of dateFormats" :key="i" :value="format"> <a-select-option v-for="(format, i) of dateFormats" :key="i" :value="format">
<div class="flex flex-row items-center"> <div class="flex flex-row items-center">
<div class="text-xs"> <div class="text-xs">

2
packages/nc-gui-v2/components/smartsheet-column/DurationOptions.vue

@ -25,7 +25,7 @@ formState.value.meta = {
</a-col> </a-col>
<a-col :span="24"> <a-col :span="24">
<a-form-item label="Duration Format"> <a-form-item label="Duration Format">
<a-select v-model:value="formState.meta.duration" size="small" class="w-52"> <a-select v-model:value="formState.meta.duration" class="w-52">
<a-select-option v-for="(duration, i) of durationOptionList" :key="i" :value="duration.id"> <a-select-option v-for="(duration, i) of durationOptionList" :key="i" :value="duration.id">
{{ duration.title }} {{ duration.title }}
</a-select-option> </a-select-option>

26
packages/nc-gui-v2/components/smartsheet-column/EditOrAdd.vue

@ -105,32 +105,26 @@ if (!formState.value?.column_name) {
</script> </script>
<template> <template>
<div class="min-w-[350px] w-max max-h-[95vh] bg-white shadow p-4 overflow-auto" @click.stop> <div class="min-w-[400px] max-h-[95vh] bg-white shadow p-6 overflow-auto" @click.stop>
<a-form v-model="formState" name="column-create-or-edit" layout="vertical"> <a-form v-model="formState" name="column-create-or-edit" layout="vertical">
<div class="flex flex-col gap-2">
<a-form-item :label="$t('labels.columnName')" v-bind="validateInfos.title"> <a-form-item :label="$t('labels.columnName')" v-bind="validateInfos.title">
<a-input ref="antInput" v-model:value="formState.title" size="small" class="nc-column-name-input" @input="onAlter(8)" /> <a-input ref="antInput" v-model:value="formState.title" class="nc-column-name-input" @input="onAlter(8)" />
</a-form-item> </a-form-item>
<a-form-item <a-form-item
v-if="!(editColumnDropdown && !!onlyNameUpdateOnEditColumns.find((col) => col === formState.uidt))" v-if="!(editColumnDropdown && !!onlyNameUpdateOnEditColumns.find((col) => col === formState.uidt))"
:label="$t('labels.columnType')" :label="$t('labels.columnType')"
> >
<a-select <a-select v-model:value="formState.uidt" show-search class="nc-column-type-input" @change="onUidtOrIdTypeChange">
v-model:value="formState.uidt"
show-search
size="small"
class="nc-column-type-input"
@change="onUidtOrIdTypeChange"
>
<a-select-option v-for="opt of uiTypesOptions" :key="opt.name" :value="opt.name" v-bind="validateInfos.uidt"> <a-select-option v-for="opt of uiTypesOptions" :key="opt.name" :value="opt.name" v-bind="validateInfos.uidt">
<div class="flex gap-1 align-center text-xs"> <div class="flex gap-1 align-center">
<component :is="opt.icon" class="text-grey" /> <component :is="opt.icon" class="text-grey" />
{{ opt.name }} {{ opt.name }}
</div> </div>
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<SmartsheetColumnFormulaOptions v-if="formState.uidt === UITypes.Formula" ref="formulaOptionsRef" /> <SmartsheetColumnFormulaOptions v-if="formState.uidt === UITypes.Formula" ref="formulaOptionsRef" />
<SmartsheetColumnCurrencyOptions v-if="formState.uidt === UITypes.Currency" /> <SmartsheetColumnCurrencyOptions v-if="formState.uidt === UITypes.Currency" />
<SmartsheetColumnDurationOptions v-if="formState.uidt === UITypes.Duration" /> <SmartsheetColumnDurationOptions v-if="formState.uidt === UITypes.Duration" />
@ -145,17 +139,17 @@ if (!formState.value?.column_name) {
<SmartsheetColumnSpecificDBTypeOptions v-if="formState.uidt === UITypes.SpecificDBType" /> <SmartsheetColumnSpecificDBTypeOptions v-if="formState.uidt === UITypes.SpecificDBType" />
<SmartsheetColumnPercentOptions v-if="formState.uidt === UITypes.Percent" /> <SmartsheetColumnPercentOptions v-if="formState.uidt === UITypes.Percent" />
<SmartsheetColumnSelectOptions v-if="formState.uidt === UITypes.SingleSelect || formState.uidt === UITypes.MultiSelect" /> <SmartsheetColumnSelectOptions v-if="formState.uidt === UITypes.SingleSelect || formState.uidt === UITypes.MultiSelect" />
</div>
<div <div
v-if="!isVirtualCol(formState.uidt)" v-if="!isVirtualCol(formState.uidt)"
class="text-xs cursor-pointer text-grey nc-more-options my-2 flex align-center gap-1 justify-end" class="text-xs cursor-pointer text-grey nc-more-options mb-1 mt-4 flex align-center gap-1 justify-end"
@click="advancedOptions = !advancedOptions" @click="advancedOptions = !advancedOptions"
> >
{{ advancedOptions ? $t('general.hideAll') : $t('general.showMore') }} {{ advancedOptions ? $t('general.hideAll') : $t('general.showMore') }}
<component :is="advancedOptions ? MdiMinusIcon : MdiPlusIcon" /> <component :is="advancedOptions ? MdiMinusIcon : MdiPlusIcon" />
</div> </div>
<div class="overflow-hidden" :class="advancedOptions ? 'h-min' : 'h-0'"> <div class="overflow-hidden" :class="advancedOptions ? 'h-min mb-2' : 'h-0'">
<a-checkbox <a-checkbox
v-if="formState.meta && columnToValidate.includes(formState.uidt)" v-if="formState.meta && columnToValidate.includes(formState.uidt)"
v-model:checked="formState.meta.validate" v-model:checked="formState.meta.validate"
@ -169,11 +163,11 @@ if (!formState.value?.column_name) {
</div> </div>
<a-form-item> <a-form-item>
<div class="flex justify-end gap-1 mt-4"> <div class="flex justify-end gap-1 mt-4">
<a-button html-type="button" size="small" @click="onCancel"> <a-button html-type="button" @click="onCancel">
<!-- Cancel --> <!-- Cancel -->
{{ $t('general.cancel') }} {{ $t('general.cancel') }}
</a-button> </a-button>
<a-button html-type="submit" type="primary" size="small" @click="onSubmit"> <a-button html-type="submit" type="primary" @click="onSubmit">
<!-- Save --> <!-- Save -->
{{ $t('general.save') }} {{ $t('general.save') }}
</a-button> </a-button>

22
packages/nc-gui-v2/components/smartsheet-column/LinkedToAnotherRecordOptions.vue

@ -41,7 +41,7 @@ const refTables = $computed(() => {
<template> <template>
<div class="w-full flex flex-col mb-2 mt-4"> <div class="w-full flex flex-col mb-2 mt-4">
<div class="border-2 p-4"> <div class="border-2 p-6">
<a-form-item v-bind="validateInfos.type"> <a-form-item v-bind="validateInfos.type">
<a-radio-group v-model:value="formState.type" name="type" v-bind="validateInfos.type"> <a-radio-group v-model:value="formState.type" name="type" v-bind="validateInfos.type">
<a-radio value="hm">Has Many</a-radio> <a-radio value="hm">Has Many</a-radio>
@ -49,7 +49,7 @@ const refTables = $computed(() => {
</a-radio-group> </a-radio-group>
</a-form-item> </a-form-item>
<a-form-item class="flex w-full pb-2 mt-4" :label="$t('labels.childTable')" v-bind="validateInfos.childId"> <a-form-item class="flex w-full pb-2 mt-4" :label="$t('labels.childTable')" v-bind="validateInfos.childId">
<a-select v-model:value="formState.childId" size="small" @change="onDataTypeChange"> <a-select v-model:value="formState.childId" @change="onDataTypeChange">
<a-select-option v-for="(table, index) in refTables" :key="index" :value="table.id"> <a-select-option v-for="(table, index) in refTables" :key="index" :value="table.id">
{{ table.title }} {{ table.title }}
</a-select-option> </a-select-option>
@ -65,29 +65,17 @@ const refTables = $computed(() => {
<component :is="advancedOptions ? MdiMinusIcon : MdiPlusIcon" /> <component :is="advancedOptions ? MdiMinusIcon : MdiPlusIcon" />
</div> </div>
<div v-if="advancedOptions" class="flex flex-col p-4 border-2 mt-2"> <div v-if="advancedOptions" class="flex flex-col p-6 gap-4 border-2 mt-2">
<div class="flex flex-row space-x-2"> <div class="flex flex-row space-x-2">
<a-form-item class="flex w-1/2" :label="$t('labels.onUpdate')"> <a-form-item class="flex w-1/2" :label="$t('labels.onUpdate')">
<a-select <a-select v-model:value="formState.onUpdate" :disabled="formState.virtual" name="onUpdate" @change="onDataTypeChange">
v-model:value="formState.onUpdate"
:disabled="formState.virtual"
name="onUpdate"
size="small"
@change="onDataTypeChange"
>
<a-select-option v-for="(option, index) in onUpdateDeleteOptions" :key="index" :value="option"> <a-select-option v-for="(option, index) in onUpdateDeleteOptions" :key="index" :value="option">
{{ option }} {{ option }}
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item class="flex w-1/2" :label="$t('labels.onDelete')"> <a-form-item class="flex w-1/2" :label="$t('labels.onDelete')">
<a-select <a-select v-model:value="formState.onDelete" :disabled="formState.virtual" name="onDelete" @change="onDataTypeChange">
v-model:value="formState.onDelete"
:disabled="formState.virtual"
name="onDelete"
size="small"
@change="onDataTypeChange"
>
<a-select-option v-for="(option, index) in onUpdateDeleteOptions" :key="index" :value="option"> <a-select-option v-for="(option, index) in onUpdateDeleteOptions" :key="index" :value="option">
{{ option }} {{ option }}
</a-select-option> </a-select-option>

16
packages/nc-gui-v2/components/smartsheet-column/LookupOptions.vue

@ -52,15 +52,10 @@ const columns = $computed(() => {
</script> </script>
<template> <template>
<div class="p-4 w-full flex flex-col border-2 mb-2 mt-4"> <div class="p-6 w-full flex flex-col border-2 mb-2 mt-4">
<div class="w-full flex flex-row space-x-2"> <div class="w-full flex flex-row space-x-2">
<a-form-item class="flex w-1/2 pb-2" :label="$t('labels.childTable')" v-bind="validateInfos.fk_relation_column_id"> <a-form-item class="flex w-1/2 pb-2" :label="$t('labels.childTable')" v-bind="validateInfos.fk_relation_column_id">
<a-select <a-select v-model:value="formState.fk_relation_column_id" dropdown-class-name="!w-64" @change="onDataTypeChange">
v-model:value="formState.fk_relation_column_id"
size="small"
dropdown-class-name="!w-64"
@change="onDataTypeChange"
>
<a-select-option v-for="(table, index) in refTables" :key="index" :value="table.col.fk_column_id"> <a-select-option v-for="(table, index) in refTables" :key="index" :value="table.col.fk_column_id">
<div class="flex flex-row space-x-0.5 h-full pb-0.5 items-center justify-between"> <div class="flex flex-row space-x-0.5 h-full pb-0.5 items-center justify-between">
<div class="font-semibold text-xs">{{ table.column.title }}</div> <div class="font-semibold text-xs">{{ table.column.title }}</div>
@ -72,12 +67,7 @@ const columns = $computed(() => {
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item class="flex w-1/2" :label="$t('labels.childColumn')" v-bind="validateInfos.fk_lookup_column_id"> <a-form-item class="flex w-1/2" :label="$t('labels.childColumn')" v-bind="validateInfos.fk_lookup_column_id">
<a-select <a-select v-model:value="formState.fk_lookup_column_id" name="fk_lookup_column_id" @change="onDataTypeChange">
v-model:value="formState.fk_lookup_column_id"
name="fk_lookup_column_id"
size="small"
@change="onDataTypeChange"
>
<a-select-option v-for="(column, index) of columns" :key="index" :value="column.id"> <a-select-option v-for="(column, index) of columns" :key="index" :value="column.id">
{{ column.title }} {{ column.title }}
</a-select-option> </a-select-option>

6
packages/nc-gui-v2/components/smartsheet-column/PercentOptions.vue

@ -11,10 +11,10 @@ if (!formState.meta?.default) formState.meta.default = null
</script> </script>
<template> <template>
<div class="flex flex-col mt-2"> <div class="flex flex-col mt-2 gap-2">
<div class="flex flex-row space-x-2"> <div class="flex flex-row space-x-2">
<a-form-item class="flex w-1/2" label="Precision"> <a-form-item class="flex w-1/2" label="Precision">
<a-select v-model:value="formState.meta.precision" size="small"> <a-select v-model:value="formState.meta.precision">
<a-select-option v-for="(precision, i) of precisions" :key="i" :value="precision.id"> <a-select-option v-for="(precision, i) of precisions" :key="i" :value="precision.id">
<div class="flex flex-row items-center"> <div class="flex flex-row items-center">
<div class="text-xs"> <div class="text-xs">
@ -25,7 +25,7 @@ if (!formState.meta?.default) formState.meta.default = null
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item label="Default Number (%)"> <a-form-item label="Default Number (%)">
<a-input v-model:value="formState.meta.default" size="small" name="default" type="number" /> <a-input v-model:value="formState.meta.default" name="default" type="number" />
</a-form-item> </a-form-item>
</div> </div>
<div class="flex flex-row mt-2"> <div class="flex flex-row mt-2">

8
packages/nc-gui-v2/components/smartsheet-column/RatingOptions.vue

@ -64,11 +64,12 @@ watch(
</script> </script>
<template> <template>
<a-row> <a-row :gutter="8">
<a-col :span="12"> <a-col :span="12">
<a-form-item label="Icon"> <a-form-item label="Icon">
<a-select v-model:value="formState.meta.iconIdx" size="small" class="w-52"> <a-select v-model:value="formState.meta.iconIdx" class="w-52">
<a-select-option v-for="(icon, i) of iconList" :key="i" :value="i"> <a-select-option v-for="(icon, i) of iconList" :key="i" :value="i">
<div class="flex items-center">
<component <component
:is="getMdiIcon(icon.full)" :is="getMdiIcon(icon.full)"
class="mx-1" class="mx-1"
@ -82,13 +83,14 @@ watch(
color: formState.meta.color, color: formState.meta.color,
}" }"
/> />
</div>
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="12"> <a-col :span="12">
<a-form-item label="Max"> <a-form-item label="Max">
<a-select v-model:value="formState.meta.max" class="w-52" size="small"> <a-select v-model:value="formState.meta.max" class="w-52">
<a-select-option v-for="(v, i) in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]" :key="i" :value="v"> <a-select-option v-for="(v, i) in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]" :key="i" :value="v">
{{ v }} {{ v }}
</a-select-option> </a-select-option>

18
packages/nc-gui-v2/components/smartsheet-column/RollupOptions.vue

@ -65,15 +65,10 @@ const columns = $computed(() => {
</script> </script>
<template> <template>
<div class="p-4 w-full flex flex-col border-2 mb-2 mt-4"> <div class="p-6 w-full flex flex-col border-2 mb-2 mt-4">
<div class="w-full flex flex-row space-x-2"> <div class="w-full flex flex-row space-x-2">
<a-form-item class="flex w-1/2 pb-2" :label="$t('labels.childTable')" v-bind="validateInfos.fk_relation_column_id"> <a-form-item class="flex w-1/2 pb-2" :label="$t('labels.childTable')" v-bind="validateInfos.fk_relation_column_id">
<a-select <a-select v-model:value="formState.fk_relation_column_id" dropdown-class-name="!w-64" @change="onDataTypeChange">
v-model:value="formState.fk_relation_column_id"
size="small"
dropdown-class-name="!w-64"
@change="onDataTypeChange"
>
<a-select-option v-for="(table, index) in refTables" :key="index" :value="table.col.fk_column_id"> <a-select-option v-for="(table, index) in refTables" :key="index" :value="table.col.fk_column_id">
<div class="flex flex-row space-x-0.5 h-full pb-0.5 items-center justify-between"> <div class="flex flex-row space-x-0.5 h-full pb-0.5 items-center justify-between">
<div class="font-semibold text-xs">{{ table.column.title }}</div> <div class="font-semibold text-xs">{{ table.column.title }}</div>
@ -85,12 +80,7 @@ const columns = $computed(() => {
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item class="flex w-1/2" :label="$t('labels.childColumn')" v-bind="validateInfos.fk_rollup_column_id"> <a-form-item class="flex w-1/2" :label="$t('labels.childColumn')" v-bind="validateInfos.fk_rollup_column_id">
<a-select <a-select v-model:value="formState.fk_rollup_column_id" name="fk_rollup_column_id" @change="onDataTypeChange">
v-model:value="formState.fk_rollup_column_id"
name="fk_rollup_column_id"
size="small"
@change="onDataTypeChange"
>
<a-select-option v-for="(column, index) of columns" :key="index" :value="column.id"> <a-select-option v-for="(column, index) of columns" :key="index" :value="column.id">
{{ column.title }} {{ column.title }}
</a-select-option> </a-select-option>
@ -98,7 +88,7 @@ const columns = $computed(() => {
</a-form-item> </a-form-item>
</div> </div>
<a-form-item label="Aggregate function" v-bind="validateInfos.rollup_function"> <a-form-item label="Aggregate function" v-bind="validateInfos.rollup_function">
<a-select v-model:value="formState.rollup_function" size="small" @change="onDataTypeChange"> <a-select v-model:value="formState.rollup_function" @change="onDataTypeChange">
<a-select-option v-for="(func, index) of aggrFunctionsList" :key="index" :value="func.value"> <a-select-option v-for="(func, index) of aggrFunctionsList" :key="index" :value="func.value">
{{ func.text }} {{ func.text }}
</a-select-option> </a-select-option>

2
packages/nc-gui-v2/components/smartsheet-column/SpecificDBTypeOptions.vue

@ -1,3 +1,3 @@
<template> <template>
<SmartsheetColumnAdvancedOptions class="mt-4" /> <SmartsheetColumnAdvancedOptions class="mt-4 mb-2" />
</template> </template>

28
packages/nc-gui-v2/components/smartsheet-header/Cell.vue

@ -16,6 +16,14 @@ const column = toRef(props, 'column')
provide(ColumnInj, column) provide(ColumnInj, column)
const editColumnDropdown = ref(false)
function onVisibleChange() {
// only allow to close the EditOrAdd component
// by clicking cancel button
editColumnDropdown.value = true
}
// instantiate column update store // instantiate column update store
useProvideColumnCreateStore(meta as Ref<TableType>, column) useProvideColumnCreateStore(meta as Ref<TableType>, column)
</script> </script>
@ -28,8 +36,26 @@ useProvideColumnCreateStore(meta as Ref<TableType>, column)
<template v-if="!hideMenu"> <template v-if="!hideMenu">
<div class="flex-1" /> <div class="flex-1" />
<SmartsheetHeaderMenu v-if="!isForm" /> <SmartsheetHeaderMenu v-if="!isForm" @edit="editColumnDropdown = true" />
</template>
<a-dropdown
v-model:visible="editColumnDropdown"
:trigger="['click']"
placement="bottomRight"
@visible-change="onVisibleChange"
>
<div />
<template #overlay>
<SmartsheetColumnEditOrAdd
class="w-full"
:edit-column-dropdown="editColumnDropdown"
@click.stop
@keydown.stop
@cancel="editColumnDropdown = false"
/>
</template> </template>
</a-dropdown>
</div> </div>
</template> </template>

24
packages/nc-gui-v2/components/smartsheet-header/Menu.vue

@ -12,8 +12,7 @@ import MdiDeleteIcon from '~icons/mdi/delete-outline'
import MdiMenuDownIcon from '~icons/mdi/menu-down' import MdiMenuDownIcon from '~icons/mdi/menu-down'
const { virtual = false } = defineProps<{ virtual?: boolean }>() const { virtual = false } = defineProps<{ virtual?: boolean }>()
const emit = defineEmits(['edit'])
const editColumnDropdown = ref(false)
const column = inject(ColumnInj) const column = inject(ColumnInj)
@ -50,31 +49,14 @@ const setAsPrimaryValue = async () => {
message.error('Failed to update primary column') message.error('Failed to update primary column')
} }
} }
function onVisibleChange() {
// only allow to close the EditOrAdd component
// by clicking cancel button
editColumnDropdown.value = true
}
</script> </script>
<template> <template>
<a-dropdown v-model:visible="editColumnDropdown" :trigger="['click']" @visible-change="onVisibleChange"> <a-dropdown placement="bottomRight" :trigger="['hover']">
<span />
<template #overlay>
<SmartsheetColumnEditOrAdd
:edit-column-dropdown="editColumnDropdown"
@click.stop
@keydown.stop
@cancel="editColumnDropdown = false"
/>
</template>
</a-dropdown>
<a-dropdown :trigger="['hover']">
<MdiMenuDownIcon class="text-grey nc-ui-dt-dropdown" /> <MdiMenuDownIcon class="text-grey nc-ui-dt-dropdown" />
<template #overlay> <template #overlay>
<a-menu class="shadow bg-white"> <a-menu class="shadow bg-white">
<a-menu-item @click="editColumnDropdown = true"> <a-menu-item @click="emit('edit')">
<div class="nc-column-edit nc-header-menu-item"> <div class="nc-column-edit nc-header-menu-item">
<MdiEditIcon class="text-primary" /> <MdiEditIcon class="text-primary" />
<!-- Edit --> <!-- Edit -->

28
packages/nc-gui-v2/components/smartsheet-header/VirtualCell.vue

@ -9,6 +9,8 @@ const props = defineProps<{ column: ColumnType & { meta: any }; hideMenu?: boole
const column = toRef(props, 'column') const column = toRef(props, 'column')
const hideMenu = toRef(props, 'hideMenu') const hideMenu = toRef(props, 'hideMenu')
const editColumnDropdown = ref(false)
provide(ColumnInj, column) provide(ColumnInj, column)
const { metas } = useMetas() const { metas } = useMetas()
@ -76,6 +78,12 @@ const tooltipMsg = computed(() => {
return '' return ''
}) })
function onVisibleChange() {
// only allow to close the EditOrAdd component
// by clicking cancel button
editColumnDropdown.value = true
}
useProvideColumnCreateStore(meta as Ref<TableType>, column) useProvideColumnCreateStore(meta as Ref<TableType>, column)
</script> </script>
@ -101,8 +109,26 @@ useProvideColumnCreateStore(meta as Ref<TableType>, column)
<template v-if="!hideMenu"> <template v-if="!hideMenu">
<v-spacer /> <v-spacer />
<SmartsheetHeaderMenu v-if="!isForm" :virtual="true" /> <SmartsheetHeaderMenu v-if="!isForm" :virtual="true" @edit="editColumnDropdown = true" />
</template>
<a-dropdown
v-model:visible="editColumnDropdown"
:trigger="['click']"
placement="bottomRight"
@visible-change="onVisibleChange"
>
<div />
<template #overlay>
<SmartsheetColumnEditOrAdd
class="w-full"
:edit-column-dropdown="editColumnDropdown"
@click.stop
@keydown.stop
@cancel="editColumnDropdown = false"
/>
</template> </template>
</a-dropdown>
</div> </div>
</template> </template>

8
packages/nc-gui-v2/components/smartsheet/Grid.vue

@ -482,10 +482,10 @@ const expandForm = (row: Row, state: Record<string, any>) => {
table, table,
td, td,
th { th {
border-right: 1px solid #7f828b33 !important; border-right: 1px solid #f0f0f0 !important;
border-left: 1px solid #7f828b33 !important; border-left: 1px solid #f0f0f0 !important;
border-bottom: 1px solid #7f828b33 !important; border-bottom: 1px solid #f0f0f0 !important;
border-top: 1px solid #7f828b33 !important; border-top: 1px solid #f0f0f0 !important;
border-collapse: collapse; border-collapse: collapse;
} }

6
packages/nc-gui-v2/components/smartsheet/Toolbar.vue

@ -5,7 +5,7 @@ const { isGrid, isForm } = useSmartsheetStoreOrThrow()
</script> </script>
<template> <template>
<div class="nc-table-toolbar w-full py-1 flex gap-1 items-center h-[48px] px-2" style="z-index: 7"> <div class="nc-table-toolbar w-full py-1 flex gap-1 items-center h-[48px] px-2 border-b" style="z-index: 7">
<SmartsheetToolbarFieldsMenu v-if="isGrid" :show-system-fields="false" class="ml-1" /> <SmartsheetToolbarFieldsMenu v-if="isGrid" :show-system-fields="false" class="ml-1" />
<SmartsheetToolbarColumnFilterMenu v-if="isGrid" /> <SmartsheetToolbarColumnFilterMenu v-if="isGrid" />
@ -26,4 +26,8 @@ const { isGrid, isForm } = useSmartsheetStoreOrThrow()
:deep(.nc-toolbar-btn) { :deep(.nc-toolbar-btn) {
@apply border-0 !text-xs font-semibold px-2; @apply border-0 !text-xs font-semibold px-2;
} }
.nc-table-toolbar {
border-color: #f0f0f0 !important;
}
</style> </style>

40
packages/nc-gui-v2/components/tabs/Auth.vue

@ -2,42 +2,48 @@
import UserManagement from './auth/UserManagement.vue' import UserManagement from './auth/UserManagement.vue'
import ApiTokenManagement from './auth/ApiTokenManagement.vue' import ApiTokenManagement from './auth/ApiTokenManagement.vue'
interface TabGroup { interface Tab {
[key: string]: {
title: string title: string
body: any body: any
} }
}
const tabsInfo: TabGroup = { const tabsInfo: Tab[] = [
usersManagement: { {
title: 'Users Management', title: 'Users Management',
body: () => UserManagement, body: () => UserManagement,
}, },
apiTokenManagement: { {
title: 'API Token Management', title: 'API Token Management',
body: () => ApiTokenManagement, body: () => ApiTokenManagement,
}, },
} ]
const firstKeyOfObject = (obj: object) => Object.keys(obj)[0] // const firstKeyOfObject = (obj: object) => Object.keys(obj)[0]
const selectedTabKeys = $ref<string[]>([firstKeyOfObject(tabsInfo)]) const selectedTabKey = $ref(0)
const selectedTab = $computed(() => tabsInfo[selectedTabKeys[0]]) const selectedTab = $computed(() => tabsInfo[selectedTabKey])
</script> </script>
<template> <template>
<div class="mt-2"> <div>
<a-menu v-model:selectedKeys="selectedTabKeys" :open-keys="[]" mode="horizontal"> <a-tabs v-model:active-key="selectedTabKey" :open-keys="[]" mode="horizontal" class="nc-auth-tabs mx-6">
<a-menu-item v-for="(tab, key) of tabsInfo" :key="key" class="select-none"> <a-tabs-tab-pane v-for="(tab, key) of tabsInfo" :key="key" class="select-none">
<div class="text-xs pb-2.5"> <template #tab>
<span>
{{ tab.title }} {{ tab.title }}
</div> </span>
</a-menu-item> </template>
</a-menu> </a-tabs-tab-pane>
</a-tabs>
<div class="mx-4 py-6 mt-2"> <div class="mx-4 py-6 mt-2">
<component :is="selectedTab.body()" /> <component :is="selectedTab.body()" />
</div> </div>
</div> </div>
</template> </template>
<style scoped>
:deep(.nc-auth-tabs .ant-tabs-nav::before) {
@apply !border-none;
}
</style>

2
packages/nc-gui-v2/components/tabs/auth/ApiTokenManagement.vue

@ -124,7 +124,7 @@ onMounted(() => {
<div class="text-gray-500">Reload</div> <div class="text-gray-500">Reload</div>
</div> </div>
</a-button> </a-button>
<a-button size="middle" @click="openNewTokenModal"> <a-button size="middle" type="primary" ghost @click="openNewTokenModal">
<div class="flex flex-row justify-center items-center caption capitalize space-x-1"> <div class="flex flex-row justify-center items-center caption capitalize space-x-1">
<MdiPlusIcon /> <MdiPlusIcon />
<div>Add New Token</div> <div>Add New Token</div>

2
packages/nc-gui-v2/components/tabs/auth/UserManagement.vue

@ -178,7 +178,7 @@ watchDebounced(searchText, () => loadUsers(), { debounce: 300, maxWait: 600 })
<div class="text-gray-500">Reload</div> <div class="text-gray-500">Reload</div>
</div> </div>
</a-button> </a-button>
<a-button v-if="isUIAllowed('newUser')" size="middle" @click="onInvite"> <a-button v-if="isUIAllowed('newUser')" size="middle" type="primary" ghost @click="onInvite">
<div class="flex flex-row justify-center items-center caption capitalize space-x-1"> <div class="flex flex-row justify-center items-center caption capitalize space-x-1">
<MidAccountIcon /> <MidAccountIcon />
<div>{{ $t('activity.inviteTeam') }}</div> <div>{{ $t('activity.inviteTeam') }}</div>

2
packages/nc-gui-v2/layouts/base.vue

@ -19,7 +19,7 @@ const logout = () => {
<div id="nc-sidebar-left" /> <div id="nc-sidebar-left" />
<a-layout class="!flex-col"> <a-layout class="!flex-col">
<a-layout-header class="flex !bg-primary items-center text-white pl-1 pr-4 shadow-lg"> <a-layout-header class="flex !bg-primary items-center text-white pl-4 pr-5 shadow-lg">
<div <div
v-if="route.name === 'index' || route.name === 'project-index-create' || route.name === 'project-index-create-external'" v-if="route.name === 'index' || route.name === 'project-index-create' || route.name === 'project-index-create-external'"
class="transition-all duration-200 p-2 cursor-pointer transform hover:scale-105" class="transition-all duration-200 p-2 cursor-pointer transform hover:scale-105"

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

@ -56,7 +56,7 @@ await loadTables()
collapsible collapsible
theme="light" theme="light"
> >
<div style="height: var(--header-height)" class="flex items-center !bg-primary text-white px-1 gap-2"> <div style="height: var(--header-height)" class="flex items-center !bg-primary text-white px-1 pl-5 gap-2">
<div <div
v-if="isOpen" v-if="isOpen"
class="w-[40px] min-w-[40px] transition-all duration-200 p-1 cursor-pointer transform hover:scale-105" class="w-[40px] min-w-[40px] transition-all duration-200 p-1 cursor-pointer transform hover:scale-105"
@ -65,7 +65,7 @@ await loadTables()
<img alt="NocoDB" src="~/assets/img/icons/512x512-trans.png" /> <img alt="NocoDB" src="~/assets/img/icons/512x512-trans.png" />
</div> </div>
<a-dropdown v-model:visible="dropdownOpen" :trigger="['click']"> <a-dropdown v-model:visible="dropdownOpen" :trigger="['click']" placement="bottom">
<div <div
:style="{ width: isOpen ? 'calc(100% - 40px) pr-2' : '100%' }" :style="{ width: isOpen ? 'calc(100% - 40px) pr-2' : '100%' }"
:class="[isOpen ? '' : 'justify-center']" :class="[isOpen ? '' : 'justify-center']"

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

@ -46,7 +46,7 @@ const icon = (tab: TabItem) => {
<div class="h-full w-full nc-container pt-[9px]"> <div class="h-full w-full nc-container pt-[9px]">
<div class="h-full w-full flex flex-col"> <div class="h-full w-full flex flex-col">
<div> <div>
<a-tabs v-model:activeKey="activeTabIndex" type="editable-card" @edit="closeTab"> <a-tabs v-model:activeKey="activeTabIndex" class="nc-root-tabs" type="editable-card" @edit="closeTab">
<a-tab-pane v-for="(tab, i) in tabs" :key="i"> <a-tab-pane v-for="(tab, i) in tabs" :key="i">
<template #tab> <template #tab>
<div class="flex align-center gap-2"> <div class="flex align-center gap-2">
@ -154,14 +154,29 @@ const icon = (tab: TabItem) => {
</div> </div>
</template> </template>
<style scoped> <style scoped lang="scss">
.nc-container { .nc-container {
height: calc(100% - var(--header-height)); height: calc(100% - var(--header-height));
flex: 1 1 100%; flex: 1 1 100%;
} }
:deep(.ant-tabs-nav) { :deep(.nc-root-tabs) {
& > .ant-tabs-nav {
@apply !mb-0; @apply !mb-0;
& > .ant-tabs-nav-wrap > .ant-tabs-nav-list {
& > .ant-tabs-nav-add {
@apply !hidden;
}
& > .ant-tabs-tab-active {
@apply font-weight-medium;
}
& > .ant-tabs-tab:not(.ant-tabs-tab-active) {
@apply bg-gray-100;
}
}
}
} }
:deep(.ant-menu-item-selected) { :deep(.ant-menu-item-selected) {
@ -173,16 +188,4 @@ const icon = (tab: TabItem) => {
:deep(.ant-menu-submenu::after) { :deep(.ant-menu-submenu::after) {
@apply !border-none; @apply !border-none;
} }
:deep(.ant-tabs-nav-add) {
@apply !hidden;
}
:deep(.ant-tabs-tab-active) {
@apply font-weight-medium;
}
:deep(.ant-tabs-tab:not(.ant-tabs-tab-active)) {
@apply bg-gray-100;
}
</style> </style>

Loading…
Cancel
Save