diff --git a/packages/nc-gui-v2/components/smartsheet/Grid.vue b/packages/nc-gui-v2/components/smartsheet/Grid.vue index 6b0172e0a2..f9294d87c3 100644 --- a/packages/nc-gui-v2/components/smartsheet/Grid.vue +++ b/packages/nc-gui-v2/components/smartsheet/Grid.vue @@ -60,6 +60,7 @@ const contextMenu = ref(false) const contextMenuTarget = ref(false) const expandedFormDlg = ref(false) const expandedFormRow = ref() +const expandedFormRowState = ref>() const visibleColLength = $computed(() => fields.value?.length) @@ -274,8 +275,9 @@ const onNavigate = (dir: NavigateDir) => { } } -const expandForm = (row: Row) => { +const expandForm = (row: Row, state: Record) => { expandedFormRow.value = row + expandedFormRowState.value = state expandedFormDlg.value = true } @@ -330,6 +332,7 @@ const expandForm = (row: Row) => { + @@ -427,7 +431,12 @@ const expandForm = (row: Row) => { - + diff --git a/packages/nc-gui-v2/components/smartsheet/Row.vue b/packages/nc-gui-v2/components/smartsheet/Row.vue index 2775b1fe68..b96120b655 100644 --- a/packages/nc-gui-v2/components/smartsheet/Row.vue +++ b/packages/nc-gui-v2/components/smartsheet/Row.vue @@ -12,12 +12,19 @@ const emit = defineEmits(['expandForm', 'selectCell', 'updateOrSaveRow', 'naviga const row = toRef(props, 'row') const { meta } = useSmartsheetStoreOrThrow() -const { isNew, state } = useProvideSmartsheetRowStore(meta, row) -watch(row, () => { - state.value = {} +const { isNew, state, syncLTARRefs } = useProvideSmartsheetRowStore(meta, row) + +// on changing isNew(new record insert) status sync LTAR cell values +watch(isNew, async (nextVal, prevVal) => { + if (prevVal && !nextVal) { + await syncLTARRefs(row.value.row) + // update row values without invoking api + row.value.row = { ...row.value.row, ...state.value } + row.value.oldRow = { ...row.value.row, ...state.value } + } }) diff --git a/packages/nc-gui-v2/components/smartsheet/expanded-form/Header.vue b/packages/nc-gui-v2/components/smartsheet/expanded-form/Header.vue index 236321daca..d559bacb81 100644 --- a/packages/nc-gui-v2/components/smartsheet/expanded-form/Header.vue +++ b/packages/nc-gui-v2/components/smartsheet/expanded-form/Header.vue @@ -1,12 +1,24 @@ diff --git a/packages/nc-gui-v2/components/virtual-cell/components/ListChildItems.vue b/packages/nc-gui-v2/components/virtual-cell/components/ListChildItems.vue index 091b0ec0fe..6544cc9794 100644 --- a/packages/nc-gui-v2/components/virtual-cell/components/ListChildItems.vue +++ b/packages/nc-gui-v2/components/virtual-cell/components/ListChildItems.vue @@ -60,7 +60,7 @@ const container = computed(() => - +
Link to '{{ meta.title }}' diff --git a/packages/nc-gui-v2/composables/useExpandedFormStore.ts b/packages/nc-gui-v2/composables/useExpandedFormStore.ts index c6b9d2a9fa..db29be43ef 100644 --- a/packages/nc-gui-v2/composables/useExpandedFormStore.ts +++ b/packages/nc-gui-v2/composables/useExpandedFormStore.ts @@ -101,6 +101,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m } const save = async () => { + let data; try { // todo: // if (this.presetValues) { @@ -116,7 +117,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m }, {} as Record) if (row.value.rowMeta.new) { - const data = await $api.dbTableRow.create('noco', project.value.title as string, meta.value.title, updateOrInsertObj) + data = await $api.dbTableRow.create('noco', project.value.title as string, meta.value.title, updateOrInsertObj) /* todo: // save hasmany and manytomany relations from local state @@ -127,7 +128,6 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m } } } */ - row.value = { row: data, rowMeta: {}, @@ -174,6 +174,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m notification.error({ message: `Failed to update row`, description: await extractSdkResponseErrorMsg(e) }) } $e('a:row-expand:add') + return data } return { diff --git a/packages/nc-gui-v2/composables/useSmartsheetRowStore.ts b/packages/nc-gui-v2/composables/useSmartsheetRowStore.ts index 20a5352596..49df3c57e2 100644 --- a/packages/nc-gui-v2/composables/useSmartsheetRowStore.ts +++ b/packages/nc-gui-v2/composables/useSmartsheetRowStore.ts @@ -1,10 +1,21 @@ -import type { ColumnType, TableType } from 'nocodb-sdk' +import { notification } from 'ant-design-vue' +import { UITypes } from 'nocodb-sdk' +import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk' import type { Ref } from 'vue' +import { useNuxtApp } from '#app' import { useInjectionState } from '#imports' +import { useMetas } from '~/composables/useMetas' +import { useProject } from '~/composables/useProject' import type { Row } from '~/composables/useViewData' import { useVirtualCell } from '~/composables/useVirtualCell' +import { NOCO } from '~/lib' +import { extractPkFromRow, extractSdkResponseErrorMsg } from '~/utils' const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState((meta: Ref, row: Ref) => { + const { $api } = useNuxtApp() + const { project } = useProject() + const { metas } = useMetas() + // state const state = ref | Record[] | null>>({}) @@ -13,25 +24,75 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState( // actions const addLTARRef = async (value: Record, column: ColumnType) => { - const { isHm, isMm } = $(useVirtualCell(ref(column))) + const { isHm, isMm, isBt } = $(useVirtualCell(ref(column))) if (isHm || isMm) { state.value[column.title!] = state.value[column.title!] || [] state.value[column.title!]!.push(value) - } else { + } else if (isBt) { state.value[column.title!] = value } } // actions const removeLTARRef = async (value: Record, column: ColumnType) => { - const { isHm, isMm } = $(useVirtualCell(ref(column))) + const { isHm, isMm, isBt } = $(useVirtualCell(ref(column))) if (isHm || isMm) { state.value[column.title!]?.splice(state.value[column.title!]?.indexOf(value), 1) - } else { + } else if (isBt) { state.value[column.title!] = null } } + const linkRecord = async (rowId: string, relatedRowId: string, column: ColumnType, type) => { + try { + await $api.dbTableRow.nestedAdd( + NOCO, + project.value.title as string, + meta.value.title as string, + rowId, + type, + column.title as string, + relatedRowId, + ) + } catch (e) { + notification.error({ + message: 'Linking failed', + description: await extractSdkResponseErrorMsg(e), + }) + } + } + + /** sync LTAR relations kept in local state */ + const syncLTARRefs = async (row: Record) => { + const id = extractPkFromRow(row, meta.value.columns as ColumnType[]) + for (const column of meta?.value?.columns ?? []) { + if (column.uidt !== UITypes.LinkToAnotherRecord) continue + const colOptions = column?.colOptions as LinkToAnotherRecordType + + const { isHm, isMm, isBt } = $(useVirtualCell(ref(column))) + const relatedTableMeta = metas.value?.[colOptions?.fk_related_model_id as string] + + if (isHm || isMm) { + const relatedRows = (state.value?.[column.title!] ?? []) as Record[] + for (const relatedRow of relatedRows) { + await linkRecord( + id, + extractPkFromRow(relatedRow, relatedTableMeta.columns as ColumnType[]), + column, + colOptions.type, + ) + } + } else if (isBt && state.value?.[column.title!]) { + await linkRecord( + id, + extractPkFromRow(state.value?.[column.title!], relatedTableMeta.columns as ColumnType[]), + column, + colOptions.type, + ) + } + } + } + return { row, state, @@ -39,6 +100,7 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState( // todo: use better name addLTARRef, removeLTARRef, + syncLTARRefs, } }, 'smartsheet-row-store')