Browse Source

fix(gui): whenever tab/view switched save any existing changes in previous view

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/3953/head
Pranav C 2 years ago
parent
commit
d1397fe12f
  1. 70
      packages/nc-gui/components/smartsheet/Grid.vue
  2. 18
      packages/nc-gui/composables/useSmartsheetRowStore.ts
  3. 28
      packages/nc-gui/composables/useViewData.ts

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

@ -1,5 +1,5 @@
<script lang="ts" setup>
import type { ColumnType } from 'nocodb-sdk'
import type { ColumnType, TableType, ViewType } from 'nocodb-sdk'
import { UITypes, isVirtualCol } from 'nocodb-sdk'
import {
ActiveViewInj,
@ -128,15 +128,6 @@ provide(CellUrlDisableOverlayInj, disableUrlOverlay)
const showLoading = ref(true)
reloadViewDataHook?.on(async (shouldShowLoading) => {
// set value if spinner should be hidden
showLoading.value = !!shouldShowLoading
await loadData()
// reset to default (showing spinner on load)
showLoading.value = true
})
const skipRowRemovalOnCancel = ref(false)
const expandForm = (row: Row, state?: Record<string, any>, fromToolbar = false) => {
@ -157,11 +148,6 @@ const expandForm = (row: Row, state?: Record<string, any>, fromToolbar = false)
}
}
openNewRecordFormHook?.on(async () => {
const newRow = await addEmptyRow()
expandForm(newRow, undefined, true)
})
const onresize = (colID: string, event: any) => {
updateWidth(colID, event.detail)
}
@ -272,30 +258,54 @@ const showContextMenu = (e: MouseEvent, target?: { row: number; col: number }) =
const rowRefs = $ref<any[]>()
/** save/update records before unmounting the component */
onBeforeUnmount(async () => {
const saveOrUpdateRecords = async (args: { metaValue?: TableType; viewMetaValue?: ViewType; data?: any } = {}) => {
let index = -1
for (const currentRow of data.value) {
for (const currentRow of args.data || data.value) {
index++
/** if new record save row and save the LTAR cells */
if (currentRow.rowMeta.new) {
const syncLTARRefs = rowRefs[index]!.syncLTARRefs
const savedRow = await updateOrSaveRow(currentRow, '')
await syncLTARRefs(savedRow)
const savedRow = await updateOrSaveRow(currentRow, '', {}, args)
await syncLTARRefs(savedRow, args)
currentRow.rowMeta.changed = false
continue
}
/** if existing row check updated cell and invoke update method */
if (currentRow.rowMeta.changed) {
currentRow.rowMeta.changed = false
for (const field of meta.value?.columns ?? []) {
for (const field of (args.metaValue || meta.value)?.columns ?? []) {
if (isVirtualCol(field)) continue
if (currentRow.row[field.title!] !== currentRow.oldRow[field.title!]) {
await updateOrSaveRow(currentRow, field.title!)
await updateOrSaveRow(currentRow, field.title!, args)
}
}
}
}
}
async function reloadViewDataHandler(shouldShowLoading: boolean | void) {
// set value if spinner should be hidden
showLoading.value = !!shouldShowLoading
await loadData()
// reset to default (showing spinner on load)
showLoading.value = true
}
async function openNewRecordHandler() {
const newRow = await addEmptyRow()
expandForm(newRow, undefined, true)
}
reloadViewDataHook?.on(reloadViewDataHandler)
openNewRecordFormHook?.on(openNewRecordHandler)
onBeforeUnmount(() => {
/** save/update records before unmounting the component */
saveOrUpdateRecords()
// reset hooks
reloadViewDataHook?.off(reloadViewDataHandler)
openNewRecordFormHook?.off(openNewRecordHandler)
})
const expandedFormOnRowIdDlg = computed({
@ -320,9 +330,21 @@ provide(ReloadRowDataHookInj, reloadViewDataHook)
// reloadViewDataHook.trigger()
watch(
() => view.value?.id,
view,
async (next, old) => {
if (next && next !== old) {
if (next && next.id !== old?.id) {
// whenever tab changes or view changes save any unsaved data
if (old?.id) {
const { getMeta } = useMetas()
const oldMeta = await getMeta(old.fk_model_id!)
if (oldMeta) {
await saveOrUpdateRecords({
viewMetaValue: old,
metaValue: oldMeta as TableType,
data: data.value,
})
}
}
await loadData()
}
},

18
packages/nc-gui/composables/useSmartsheetRowStore.ts

@ -65,12 +65,18 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState(
}
}
const linkRecord = async (rowId: string, relatedRowId: string, column: ColumnType, type: RelationTypes) => {
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,
meta.value?.title as string,
metaValue?.title as string,
rowId,
type as 'mm' | 'hm',
column.title as string,
@ -82,9 +88,9 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState(
}
/** sync LTAR relations kept in local state */
const syncLTARRefs = async (row: Record<string, any>) => {
const id = extractPkFromRow(row, meta.value?.columns as ColumnType[])
for (const column of meta?.value?.columns ?? []) {
const syncLTARRefs = async (row: Record<string, any>, { 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
@ -99,6 +105,7 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState(
extractPkFromRow(relatedRow, relatedTableMeta.columns as ColumnType[]),
column,
colOptions.type as RelationTypes,
{ metaValue },
)
}
} else if (isBt && state?.value?.[column.title!]) {
@ -107,6 +114,7 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState(
extractPkFromRow(state.value?.[column.title!] as Record<string, any>, relatedTableMeta.columns as ColumnType[]),
column,
colOptions.type as RelationTypes,
{ metaValue },
)
}
}

28
packages/nc-gui/composables/useViewData.ts

@ -200,12 +200,13 @@ export function useViewData(
row: Record<string, any>,
rowIndex = formattedData.value?.length,
ltarState: Record<string, any> = {},
{ metaValue = meta.value, viewMetaValue = viewMeta.value }: { metaValue?: TableType; viewMetaValue?: ViewType } = {},
) {
try {
const { getMeta } = useMetas()
const { missingRequiredColumns, insertObj } = await populateInsertObject({
meta: meta.value!,
meta: metaValue!,
ltarState,
getMeta,
row,
@ -216,8 +217,8 @@ export function useViewData(
const insertedData = await $api.dbViewRow.create(
NOCO,
project?.value.id as string,
meta.value?.id as string,
viewMeta?.value?.id as string,
metaValue?.id as string,
viewMetaValue?.id as string,
insertObj,
)
@ -234,15 +235,19 @@ export function useViewData(
}
}
async function updateRowProperty(toUpdate: Row, property: string) {
async function updateRowProperty(
toUpdate: Row,
property: string,
{ metaValue = meta.value, viewMetaValue = viewMeta.value }: { metaValue?: TableType; viewMetaValue?: ViewType } = {},
) {
try {
const id = extractPkFromRow(toUpdate.row, meta.value?.columns as ColumnType[])
const updatedRowData = await $api.dbViewRow.update(
NOCO,
project?.value.id as string,
meta.value?.id as string,
viewMeta?.value?.id as string,
metaValue?.id as string,
viewMetaValue?.id as string,
id,
{
[property]: toUpdate.row[property],
@ -271,11 +276,16 @@ export function useViewData(
}
}
async function updateOrSaveRow(row: Row, property?: string, ltarState?: Record<string, any>) {
async function updateOrSaveRow(
row: Row,
property?: string,
ltarState?: Record<string, any>,
args: { metaValue?: TableType; viewMetaValue?: ViewType } = {},
) {
if (row.rowMeta.new) {
return await insertRow(row.row, formattedData.value.indexOf(row), ltarState)
return await insertRow(row.row, formattedData.value.indexOf(row), ltarState, args)
} else {
await updateRowProperty(row, property!)
await updateRowProperty(row, property!, args)
}
}

Loading…
Cancel
Save