From 64e37fa344c85a49ecdf86d0c65ac5d21433ed6d Mon Sep 17 00:00:00 2001 From: mertmit Date: Wed, 21 Jun 2023 18:39:26 +0300 Subject: [PATCH 1/3] feat: recover LTAR when undoing delete Signed-off-by: mertmit --- packages/nc-gui/composables/useViewData.ts | 75 +++++++++++++++++++++- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/packages/nc-gui/composables/useViewData.ts b/packages/nc-gui/composables/useViewData.ts index 34bb78db9b..1e8ef11365 100644 --- a/packages/nc-gui/composables/useViewData.ts +++ b/packages/nc-gui/composables/useViewData.ts @@ -1,5 +1,16 @@ import { UITypes, ViewTypes } from 'nocodb-sdk' -import type { Api, ColumnType, FormColumnType, FormType, GalleryType, PaginatedType, TableType, ViewType } from 'nocodb-sdk' +import type { + Api, + ColumnType, + FormColumnType, + FormType, + GalleryType, + LinkToAnotherRecordType, + PaginatedType, + RelationTypes, + TableType, + ViewType, +} from 'nocodb-sdk' import type { ComputedRef, Ref } from 'vue' import type { CellRange } from '#imports' import { @@ -54,7 +65,7 @@ export function useViewData( const { appInfo } = $(useGlobal()) - const { getMeta } = useMetas() + const { getMeta, metas } = useMetas() const { addUndo, clone, defineViewScope } = useUndoRedo() @@ -335,7 +346,7 @@ export function useViewData( try { const id = extractPkFromRow(toUpdate.row, metaValue?.columns as ColumnType[]) - const updatedRowData = await $api.dbViewRow.update( + const updatedRowData: Record = await $api.dbViewRow.update( NOCO, project?.value.id as string, metaValue?.id as string, @@ -575,6 +586,62 @@ export function useViewData( $e('a:grid:pagination') } + const linkRecord = async ( + rowId: string, + relatedRowId: string, + column: ColumnType, + type: RelationTypes, + { metaValue = meta.value }: { metaValue?: TableType } = {}, + ) => { + try { + await $api.dbTableRow.nestedAdd( + NOCO, + project.value.title as string, + metaValue?.title as string, + rowId, + type as 'mm' | 'hm', + column.title as string, + relatedRowId, + ) + } catch (e: any) { + message.error(await extractSdkResponseErrorMsg(e)) + } + } + + // Recover LTAR relations for a row using the row data + const recoverLTARRefs = async (row: Record, { metaValue = meta.value }: { metaValue?: TableType } = {}) => { + const id = extractPkFromRow(row, metaValue?.columns as ColumnType[]) + for (const column of metaValue?.columns ?? []) { + if (column.uidt !== UITypes.LinkToAnotherRecord) continue + + const colOptions = column.colOptions as LinkToAnotherRecordType + + const relatedTableMeta = metas.value?.[colOptions?.fk_related_model_id as string] + + if (isHm(column) || isMm(column)) { + const relatedRows = (row[column.title!] ?? []) as Record[] + + for (const relatedRow of relatedRows) { + await linkRecord( + id, + extractPkFromRow(relatedRow, relatedTableMeta.columns as ColumnType[]), + column, + colOptions.type as RelationTypes, + { metaValue }, + ) + } + } else if (isBt(column) && row[column.title!]) { + await linkRecord( + id, + extractPkFromRow(row[column.title!] as Record, relatedTableMeta.columns as ColumnType[]), + column, + colOptions.type as RelationTypes, + { metaValue }, + ) + } + } + } + async function deleteRowById( id: string, { metaValue = meta.value, viewMetaValue = viewMeta.value }: { metaValue?: TableType; viewMetaValue?: ViewType } = {}, @@ -638,6 +705,7 @@ export function useViewData( const pkData = rowPkData(row.row, meta.value?.columns as ColumnType[]) row.row = { ...pkData, ...row.row } await insertRow(row, ltarState, {}, true) + recoverLTARRefs(row.row) if (rowIndex !== -1 && pg.pageSize === paginationData.value.pageSize) { if (pg.page === paginationData.value.page) { formattedData.value.splice(rowIndex, 0, row) @@ -714,6 +782,7 @@ export function useViewData( const pkData = rowPkData(row.row, meta.value?.columns as ColumnType[]) row.row = { ...pkData, ...row.row } await insertRow(row, {}, {}, true) + recoverLTARRefs(row.row) if (rowIndex !== -1 && pg.pageSize === paginationData.value.pageSize) { if (pg.page === paginationData.value.page) { formattedData.value.splice(rowIndex, 0, row) From 1c907fc6e4872b269b9d0320fcce2c3682a268a5 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Thu, 22 Jun 2023 09:17:22 +0530 Subject: [PATCH 2/3] test: delete row with links, undo Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- tests/playwright/tests/db/undo-redo.spec.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/playwright/tests/db/undo-redo.spec.ts b/tests/playwright/tests/db/undo-redo.spec.ts index 7e6746a623..fc1c5abdb1 100644 --- a/tests/playwright/tests/db/undo-redo.spec.ts +++ b/tests/playwright/tests/db/undo-redo.spec.ts @@ -589,6 +589,25 @@ test.describe('Undo Redo - LTAR', () => { await undo({ page, values: ['Mumbai'] }); await undo({ page, values: [] }); }); + + test('Row with links: Delete & Undo', async ({ page }) => { + await dashboard.closeTab({ title: 'Team & Auth' }); + await dashboard.treeView.openTable({ title: 'Country' }); + + await grid.cell.inCellAdd({ index: 0, columnHeader: 'CityList' }); + await dashboard.linkRecord.select('Mumbai'); + + await grid.cell.inCellAdd({ index: 0, columnHeader: 'CityList' }); + await dashboard.linkRecord.select('Delhi'); + + await grid.deleteRow(0, 'Country'); + await dashboard.rootPage.waitForTimeout(200); + await page.keyboard.press((await grid.isMacOs()) ? 'Meta+z' : 'Control+z'); + await dashboard.rootPage.waitForTimeout(200); + await verifyRecords(['Mumbai', 'Delhi']); + await dashboard.rootPage.reload(); + await verifyRecords(['Mumbai', 'Delhi']); + }); }); test.describe('Undo Redo - Select based', () => { From 446400d64130d448fd32ff45231c8cb8a4513209 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Thu, 22 Jun 2023 10:37:16 +0530 Subject: [PATCH 3/3] test: enable row delete test undo only for sqlite Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- tests/playwright/tests/db/undo-redo.spec.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/playwright/tests/db/undo-redo.spec.ts b/tests/playwright/tests/db/undo-redo.spec.ts index fc1c5abdb1..52b402bf4c 100644 --- a/tests/playwright/tests/db/undo-redo.spec.ts +++ b/tests/playwright/tests/db/undo-redo.spec.ts @@ -5,6 +5,7 @@ import { Api, UITypes } from 'nocodb-sdk'; import { rowMixedValue } from '../../setup/xcdb-records'; import { GridPage } from '../../pages/Dashboard/Grid'; import { ToolbarPage } from '../../pages/Dashboard/common/Toolbar'; +import { isSqlite } from '../../setup/db'; let dashboard: DashboardPage, grid: GridPage, @@ -591,6 +592,10 @@ test.describe('Undo Redo - LTAR', () => { }); test('Row with links: Delete & Undo', async ({ page }) => { + // SQLite has foreign key constraint disabled by default & hence below test + // will work even for ext DB + if (!isSqlite(context)) test.skip(); + await dashboard.closeTab({ title: 'Team & Auth' }); await dashboard.treeView.openTable({ title: 'Country' });