Browse Source

feat: draggable data sources

Signed-off-by: mertmit <mertmit99@gmail.com>
pull/3573/head
mertmit 2 years ago
parent
commit
b0695f5e0e
  1. 311
      packages/nc-gui/components/dashboard/settings/DataSources.vue

311
packages/nc-gui/components/dashboard/settings/DataSources.vue

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import Draggable from 'vuedraggable'
import { Empty } from 'ant-design-vue' import { Empty } from 'ant-design-vue'
import type { BaseType } from 'nocodb-sdk' import type { BaseType } from 'nocodb-sdk'
import type { CheckboxChangeEvent } from 'ant-design-vue/lib/checkbox/interface' import type { CheckboxChangeEvent } from 'ant-design-vue/lib/checkbox/interface'
@ -64,9 +65,10 @@ async function loadMetaDiff() {
} }
} }
const baseAction = (baseId: string, action: string) => { const baseAction = (baseId?: string, action?: string) => {
if (!baseId) return
activeBaseId = baseId activeBaseId = baseId
vState.value = action vState.value = action || ''
} }
const deleteBase = (base: BaseType) => { const deleteBase = (base: BaseType) => {
@ -107,22 +109,26 @@ const toggleBase = async (base: BaseType, e: CheckboxChangeEvent) => {
} }
} }
const moveBase = async (base: BaseType, direction: 'up' | 'down') => { const moveBase = async (e: any) => {
try { try {
if (!base.order) { if (e.oldIndex === e.newIndex) return
// empty update call to reorder bases (migration) // sources list is mutated so we have to get the new index and mirror it to backend
await $api.base.update(base.project_id as string, base.id as string, { const base = sources[e.newIndex]
id: base.id, if (base) {
project_id: base.project_id, if (!base.order) {
}) // empty update call to reorder bases (migration)
message.info('Bases are migrated. Please try again.') await $api.base.update(base.project_id as string, base.id as string, {
} else { id: base.id,
direction === 'up' ? base.order-- : base.order++ project_id: base.project_id,
await $api.base.update(base.project_id as string, base.id as string, { })
id: base.id, message.info('Bases are migrated. Please try again.')
project_id: base.project_id, } else {
order: base.order, await $api.base.update(base.project_id as string, base.id as string, {
}) id: base.id,
project_id: base.project_id,
order: e.newIndex + 1,
})
}
} }
await loadProject() await loadProject()
await loadBases() await loadBases()
@ -174,104 +180,157 @@ watch(
<template> <template>
<div class="flex flex-row w-full"> <div class="flex flex-row w-full">
<div class="flex flex-col w-full"> <div class="flex flex-col w-full overflow-auto">
<div v-if="vState === ''" class="max-h-600px overflow-y-auto"> <div v-if="vState === ''" class="max-h-600px min-w-1200px overflow-y-auto">
<a-table <div class="ds-table-head">
class="w-full" <div class="ds-table-row">
size="small" <div class="ds-table-col ds-table-enabled"></div>
:custom-row=" <div class="ds-table-col ds-table-name">Name</div>
(record) => ({ <div class="ds-table-col ds-table-actions">Actions</div>
class: `nc-datasource-row nc-datasource-row-${record.table_name}`, </div>
}) </div>
" <div class="ds-table-body">
:data-source="sources ?? []" <Draggable :list="sources" item-key="id" handle=".ds-table-handle" @end="moveBase">
:pagination="false" <template #header>
:loading="vReload" <div v-if="sources[0]" class="ds-table-row border-gray-200">
bordered <div class="ds-table-col ds-table-enabled"></div>
>
<template #emptyText> <a-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" :description="$t('labels.noData')" /> </template> <div class="ds-table-col ds-table-name">
<a-table-column key="enabled" data-index="enabled" :width="30"> <div class="flex items-center gap-1">
<template #default="{ record }"> <GeneralBaseLogo :base-type="sources[0].type" />
<div v-if="!record.is_meta" class="flex items-center gap-1"> BASE
<a-tooltip> <span class="text-gray-400 text-xs">({{ sources[0].type }})</span>
<template #title>Show in UI</template> </div>
<a-checkbox :checked="record.enabled ? true : false" @change="toggleBase(record, $event)"></a-checkbox> </div>
</a-tooltip>
</div> <div class="ds-table-col ds-table-actions">
</template> <div class="flex items-center gap-2">
</a-table-column> <a-button
<a-table-column key="order" width="60px"> class="nc-action-btn cursor-pointer outline-0"
<template #default="{ record, index }"> @click="baseAction(sources[0].id, DataSourcesSubTab.Metadata)"
<div class="flex items-center gap-1 text-gray-600 font-light"> >
<MdiArrowUpBox <div class="flex items-center gap-2 text-gray-600 font-light">
v-if="!record.is_meta && index !== 1" <a-tooltip v-if="metadiffbases.includes(sources[0].id as string)">
class="text-lg group-hover:text-accent" <template #title>Out of sync</template>
@click="moveBase(record, 'up')" <MdiDatabaseAlert class="text-lg group-hover:text-accent text-primary" />
/> </a-tooltip>
<MdiArrowDownBox <MdiDatabaseSync v-else class="text-lg group-hover:text-accent" />
v-if="!record.is_meta && index !== sources.length - 1" Sync Metadata
class="text-lg group-hover:text-accent" </div>
@click="moveBase(record, 'down')" </a-button>
/> <a-button
</div> class="nc-action-btn cursor-pointer outline-0"
</template> @click="baseAction(sources[0].id, DataSourcesSubTab.UIAcl)"
</a-table-column> >
<a-table-column key="alias" title="Name" data-index="alias"> <div class="flex items-center gap-2 text-gray-600 font-light">
<template #default="{ text, record }"> <MdiDatabaseLockOutline class="text-lg group-hover:text-accent" />
<div class="flex items-center gap-1"> UI ACL
<GeneralBaseLogo :base-type="record.type" /> </div>
{{ record.is_meta ? 'BASE' : text }} <span class="text-gray-400 text-xs">({{ record.type }})</span> </a-button>
<a-button
class="nc-action-btn cursor-pointer outline-0"
@click="baseAction(sources[0].id, DataSourcesSubTab.ERD)"
>
<div class="flex items-center gap-2 text-gray-600 font-light">
<MdiGraphOutline class="text-lg group-hover:text-accent" />
ERD
</div>
</a-button>
<a-button
v-if="!sources[0].is_meta"
class="nc-action-btn cursor-pointer outline-0"
@click="baseAction(sources[0].id, DataSourcesSubTab.Edit)"
>
<div class="flex items-center gap-2 text-gray-600 font-light">
<MdiEditOutline class="text-lg group-hover:text-accent" />
Edit
</div>
</a-button>
<a-button
v-if="!sources[0].is_meta"
class="nc-action-btn cursor-pointer outline-0"
@click="deleteBase(sources[0])"
>
<div class="flex items-center gap-2 text-red-500 font-light">
<MdiDeleteOutline class="text-lg group-hover:text-accent" />
Delete
</div>
</a-button>
</div>
</div>
</div> </div>
</template> </template>
</a-table-column> <template #item="{ element: base, index }">
<a-table-column key="action" :title="$t('labels.actions')" :width="180"> <div v-if="index !== 0" class="ds-table-row border-gray-200">
<template #default="{ record }"> <div class="ds-table-col ds-table-enabled">
<div class="flex items-center gap-2"> <MdiDragVertical small class="ds-table-handle" />
<a-button <div v-if="!base.is_meta" class="flex items-center gap-1">
class="nc-action-btn cursor-pointer outline-0" <a-tooltip>
@click="baseAction(record.id, DataSourcesSubTab.Metadata)" <template #title>Show in UI</template>
> <a-checkbox :checked="base.enabled ? true : false" @change="toggleBase(base, $event)"></a-checkbox>
<div class="flex items-center gap-2 text-gray-600 font-light">
<a-tooltip v-if="metadiffbases.includes(record.id)">
<template #title>Out of sync</template>
<MdiDatabaseAlert class="text-lg group-hover:text-accent text-primary" />
</a-tooltip> </a-tooltip>
<MdiDatabaseSync v-else class="text-lg group-hover:text-accent" />
Sync Metadata
</div>
</a-button>
<a-button class="nc-action-btn cursor-pointer outline-0" @click="baseAction(record.id, DataSourcesSubTab.UIAcl)">
<div class="flex items-center gap-2 text-gray-600 font-light">
<MdiDatabaseLockOutline class="text-lg group-hover:text-accent" />
UI ACL
</div> </div>
</a-button> </div>
<a-button class="nc-action-btn cursor-pointer outline-0" @click="baseAction(record.id, DataSourcesSubTab.ERD)">
<div class="flex items-center gap-2 text-gray-600 font-light"> <div class="ds-table-col ds-table-name">
<MdiGraphOutline class="text-lg group-hover:text-accent" /> <div class="flex items-center gap-1">
ERD <GeneralBaseLogo :base-type="base.type" />
</div> {{ base.is_meta ? 'BASE' : base.alias }} <span class="text-gray-400 text-xs">({{ base.type }})</span>
</a-button>
<a-button
v-if="!record.is_meta"
class="nc-action-btn cursor-pointer outline-0"
@click="baseAction(record.id, DataSourcesSubTab.Edit)"
>
<div class="flex items-center gap-2 text-gray-600 font-light">
<MdiEditOutline class="text-lg group-hover:text-accent" />
Edit
</div> </div>
</a-button> </div>
<a-button v-if="!record.is_meta" class="nc-action-btn cursor-pointer outline-0" @click="deleteBase(record)">
<div class="flex items-center gap-2 text-red-500 font-light"> <div class="ds-table-col ds-table-actions">
<MdiDeleteOutline class="text-lg group-hover:text-accent" /> <div class="flex items-center gap-2">
Delete <a-button
class="nc-action-btn cursor-pointer outline-0"
@click="baseAction(base.id, DataSourcesSubTab.Metadata)"
>
<div class="flex items-center gap-2 text-gray-600 font-light">
<a-tooltip v-if="metadiffbases.includes(base.id as string)">
<template #title>Out of sync</template>
<MdiDatabaseAlert class="text-lg group-hover:text-accent text-primary" />
</a-tooltip>
<MdiDatabaseSync v-else class="text-lg group-hover:text-accent" />
Sync Metadata
</div>
</a-button>
<a-button
class="nc-action-btn cursor-pointer outline-0"
@click="baseAction(base.id, DataSourcesSubTab.UIAcl)"
>
<div class="flex items-center gap-2 text-gray-600 font-light">
<MdiDatabaseLockOutline class="text-lg group-hover:text-accent" />
UI ACL
</div>
</a-button>
<a-button class="nc-action-btn cursor-pointer outline-0" @click="baseAction(base.id, DataSourcesSubTab.ERD)">
<div class="flex items-center gap-2 text-gray-600 font-light">
<MdiGraphOutline class="text-lg group-hover:text-accent" />
ERD
</div>
</a-button>
<a-button
v-if="!base.is_meta"
class="nc-action-btn cursor-pointer outline-0"
@click="baseAction(base.id, DataSourcesSubTab.Edit)"
>
<div class="flex items-center gap-2 text-gray-600 font-light">
<MdiEditOutline class="text-lg group-hover:text-accent" />
Edit
</div>
</a-button>
<a-button v-if="!base.is_meta" class="nc-action-btn cursor-pointer outline-0" @click="deleteBase(base)">
<div class="flex items-center gap-2 text-red-500 font-light">
<MdiDeleteOutline class="text-lg group-hover:text-accent" />
Delete
</div>
</a-button>
</div> </div>
</a-button> </div>
</div> </div>
</template> </template>
</a-table-column> </Draggable>
</a-table> </div>
</div> </div>
<div v-else-if="vState === DataSourcesSubTab.New" class="max-h-600px overflow-y-auto"> <div v-else-if="vState === DataSourcesSubTab.New" class="max-h-600px overflow-y-auto">
<CreateBase :connection-type="clientType" @base-created="loadBases" /> <CreateBase :connection-type="clientType" @base-created="loadBases" />
@ -291,3 +350,41 @@ watch(
</div> </div>
</div> </div>
</template> </template>
<style>
.ds-table-head {
@apply flex items-center border-t bg-gray-100 font-bold text-gray-500;
}
.ds-table-body {
@apply flex flex-col;
}
.ds-table-row {
@apply grid grid-cols-20 border-b w-full h-full border-l border-r;
}
.ds-table-col {
@apply flex items-center p-3 border-r-1 mr-2 h-50px;
}
.ds-table-enabled {
@apply col-span-1 w-full flex gap-2;
}
.ds-table-name {
@apply col-span-9;
}
.ds-table-actions {
@apply col-span-10;
}
.ds-table-col:last-child {
@apply border-r-0;
}
.ds-table-handle {
@apply cursor-pointer justify-self-start;
}
</style>

Loading…
Cancel
Save