|
|
@ -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))]; |
|
|
|
} |
|
|
|
} |
|
|
@ -271,7 +265,7 @@ const activeTable = computed(() => { |
|
|
|
@apply !pointer-events-none; |
|
|
|
@apply !pointer-events-none; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
&.dragging { |
|
|
|
& .dragging { |
|
|
|
.nc-icon { |
|
|
|
.nc-icon { |
|
|
|
@apply !hidden; |
|
|
|
@apply !hidden; |
|
|
|
} |
|
|
|
} |
|
|
@ -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> |
|
|
|