Browse Source

feat: drag-n-drop LTAR and Lookup creation

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/5807/head
Pranav C 2 years ago
parent
commit
373c3e3902
  1. 11
      packages/nc-gui/components/dashboard/TreeView.vue
  2. 10
      packages/nc-gui/components/smartsheet/Grid.vue
  3. 15
      packages/nc-gui/components/smartsheet/column/EditOrAdd.vue
  4. 10
      packages/nc-gui/components/smartsheet/column/EditOrAddProvider.vue
  5. 67
      packages/nc-gui/components/tabs/Smartsheet.vue

11
packages/nc-gui/components/dashboard/TreeView.vue

@ -184,6 +184,15 @@ const initSortable = (el: Element) => {
}) })
}, },
animation: 150, animation: 150,
setData(dataTransfer, dragEl) {
dataTransfer.setData(
'text/json',
JSON.stringify({
id: dragEl.dataset.id,
title: dragEl.dataset.title,
}),
)
},
}) })
} }
@ -699,6 +708,7 @@ const duplicateTable = async (table: TableType) => {
class="nc-tree-item text-sm cursor-pointer group" class="nc-tree-item text-sm cursor-pointer group"
:data-order="table.order" :data-order="table.order"
:data-id="table.id" :data-id="table.id"
:data-title="table.title"
:data-testid="`tree-view-table-${table.title}`" :data-testid="`tree-view-table-${table.title}`"
@click="addTableTab(table)" @click="addTableTab(table)"
> >
@ -1023,6 +1033,7 @@ const duplicateTable = async (table: TableType) => {
class="nc-tree-item text-sm cursor-pointer group" class="nc-tree-item text-sm cursor-pointer group"
:data-order="table.order" :data-order="table.order"
:data-id="table.id" :data-id="table.id"
:data-title="table.title"
:data-testid="`tree-view-table-${table.title}`" :data-testid="`tree-view-table-${table.title}`"
@click="addTableTab(table)" @click="addTableTab(table)"
> >

10
packages/nc-gui/components/smartsheet/Grid.vue

@ -428,6 +428,8 @@ const showLoading = ref(true)
const skipRowRemovalOnCancel = ref(false) const skipRowRemovalOnCancel = ref(false)
const preloadColumn = ref<Partial<any>>()
function expandForm(row: Row, state?: Record<string, any>, fromToolbar = false) { function expandForm(row: Row, state?: Record<string, any>, fromToolbar = false) {
const rowId = extractPkFromRow(row.row, meta.value?.columns as ColumnType[]) const rowId = extractPkFromRow(row.row, meta.value?.columns as ColumnType[])
@ -457,6 +459,13 @@ const onXcResizing = (cn: string, event: any) => {
defineExpose({ defineExpose({
loadData, loadData,
openColumnCreate: (data) => {
tableHead.value?.querySelector('th:last-child')?.scrollIntoView({ behavior: 'smooth' })
setTimeout(() => {
addColumnDropdown.value = true
preloadColumn.value = data
}, 500)
},
}) })
// reset context menu target on hide // reset context menu target on hide
@ -869,6 +878,7 @@ const confirmDeleteRow = (row: number) => {
<template #overlay> <template #overlay>
<SmartsheetColumnEditOrAddProvider <SmartsheetColumnEditOrAddProvider
v-if="addColumnDropdown" v-if="addColumnDropdown"
:preload="preloadColumn"
:column-position="columnOrder" :column-position="columnOrder"
@submit="closeAddColumnDropdown" @submit="closeAddColumnDropdown"
@cancel="closeAddColumnDropdown" @cancel="closeAddColumnDropdown"

15
packages/nc-gui/components/smartsheet/column/EditOrAdd.vue

@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { ColumnReqType } from 'nocodb-sdk' import type { ColumnReqType, ColumnType } from 'nocodb-sdk'
import { UITypes, isVirtualCol } from 'nocodb-sdk' import { UITypes, isVirtualCol } from 'nocodb-sdk'
import { import {
IsFormInj, IsFormInj,
@ -25,6 +25,7 @@ import MdiMinusIcon from '~icons/mdi/minus-circle-outline'
import MdiIdentifierIcon from '~icons/mdi/identifier' import MdiIdentifierIcon from '~icons/mdi/identifier'
const props = defineProps<{ const props = defineProps<{
preload?: Partial<ColumnType>
columnPosition?: Pick<ColumnReqType, 'column_order'> columnPosition?: Pick<ColumnReqType, 'column_order'>
}>() }>()
@ -125,6 +126,18 @@ watchEffect(() => {
onMounted(() => { onMounted(() => {
if (!isEdit.value) { if (!isEdit.value) {
generateNewColumnMeta() generateNewColumnMeta()
const { colOptions, ...others } = props.preload || {}
formState.value = {
...formState.value,
...others,
}
if (colOptions) {
onUidtOrIdTypeChange()
formState.value = {
...formState.value,
...colOptions,
}
}
} else { } else {
if (formState.value.pk) { if (formState.value.pk) {
message.info(t('msg.info.editingPKnotSupported')) message.info(t('msg.info.editingPKnotSupported'))

10
packages/nc-gui/components/smartsheet/column/EditOrAddProvider.vue

@ -6,6 +6,7 @@ import { MetaInj, inject, ref, toRef, useProvideColumnCreateStore } from '#impor
interface Props { interface Props {
column?: ColumnType column?: ColumnType
columnPosition?: Pick<ColumnReqType, 'column_order'> columnPosition?: Pick<ColumnReqType, 'column_order'>
preload?: Partial<ColumnType>
} }
const props = defineProps<Props>() const props = defineProps<Props>()
@ -16,9 +17,16 @@ const meta = inject(MetaInj, ref())
const column = toRef(props, 'column') const column = toRef(props, 'column')
const preload = toRef(props, 'preload')
useProvideColumnCreateStore(meta, column) useProvideColumnCreateStore(meta, column)
</script> </script>
<template> <template>
<SmartsheetColumnEditOrAdd :column-position="props.columnPosition" @submit="emit('submit')" @cancel="emit('cancel')" /> <SmartsheetColumnEditOrAdd
:preload="preload"
:column-position="props.columnPosition"
@submit="emit('submit')"
@cancel="emit('cancel')"
/>
</template> </template>

67
packages/nc-gui/components/tabs/Smartsheet.vue

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ColumnType, TableType } from 'nocodb-sdk' import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk'
import { UITypes } from 'nocodb-sdk'
import { import {
ActiveViewInj, ActiveViewInj,
FieldsInj, FieldsInj,
@ -29,7 +30,7 @@ const props = defineProps<{
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useUIPermission()
const { metas } = useMetas() const { metas, getMeta } = useMetas()
const activeTab = toRef(props, 'activeTab') const activeTab = toRef(props, 'activeTab')
@ -64,10 +65,68 @@ provide(
ReadonlyInj, ReadonlyInj,
computed(() => !isUIAllowed('xcDatatableEditable')), computed(() => !isUIAllowed('xcDatatableEditable')),
) )
const grid = ref()
const onDrop = async (event: DragEvent) => {
event.preventDefault()
try {
// Access the dropped data
const data = JSON.parse(event.dataTransfer?.getData('text/json')!)
// Do something with the received data
const childMeta = await getMeta(data.id)
const parentMeta = metas.value[meta.value.id!]
if (!childMeta || !parentMeta) return
const parentPkCol = parentMeta.columns?.find((c) => c.pk)
const childPkCol = childMeta.columns?.find((c) => c.pk)
// if already a link column exists, create a new Lookup column
const relationCol = parentMeta.columns?.find((c: ColumnType) => {
if (c.uidt !== UITypes.LinkToAnotherRecord) return false
const ltarOptions = c.colOptions as LinkToAnotherRecordType
if (ltarOptions.type !== 'mm') {
return false
}
if (ltarOptions.fk_related_model_id === childMeta.id) {
return true
}
return false
})
if (relationCol) {
const lookupCol = childMeta.columns?.find((c) => c.pv) ?? childMeta.columns?.[0]
grid.value?.openColumnCreate({
uidt: UITypes.Lookup,
title: `${data.title}Lookup`,
fk_relation_column_id: relationCol.id,
fk_lookup_column_id: lookupCol?.id,
})
} else {
grid.value?.openColumnCreate({
uidt: UITypes.LinkToAnotherRecord,
title: `${data.title}List`,
parentId: parentMeta.id,
childId: childMeta.id,
parentTable: parentMeta.title,
parentColumn: parentPkCol.title,
childTable: childMeta.title,
childColumn: childPkCol?.title,
})
}
} catch (e) {
console.log('error', e)
}
}
</script> </script>
<template> <template>
<div class="nc-container flex h-full"> <div class="nc-container flex h-full" @drop="onDrop" @dragover.prevent>
<div class="flex flex-col h-full flex-1 min-w-0"> <div class="flex flex-col h-full flex-1 min-w-0">
<LazySmartsheetToolbar /> <LazySmartsheetToolbar />
@ -75,7 +134,7 @@ provide(
<template v-if="meta"> <template v-if="meta">
<div class="flex flex-1 min-h-0"> <div class="flex flex-1 min-h-0">
<div v-if="activeView" class="h-full flex-1 min-w-0 min-h-0 bg-gray-50"> <div v-if="activeView" class="h-full flex-1 min-w-0 min-h-0 bg-gray-50">
<LazySmartsheetGrid v-if="isGrid" /> <LazySmartsheetGrid v-if="isGrid" ref="grid" />
<LazySmartsheetGallery v-else-if="isGallery" /> <LazySmartsheetGallery v-else-if="isGallery" />

Loading…
Cancel
Save