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> <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 { UITypes, isVirtualCol } from 'nocodb-sdk'
import { import {
ActiveViewInj, ActiveViewInj,
@ -128,15 +128,6 @@ provide(CellUrlDisableOverlayInj, disableUrlOverlay)
const showLoading = ref(true) 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 skipRowRemovalOnCancel = ref(false)
const expandForm = (row: Row, state?: Record<string, any>, fromToolbar = 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) => { const onresize = (colID: string, event: any) => {
updateWidth(colID, event.detail) updateWidth(colID, event.detail)
} }
@ -272,30 +258,54 @@ const showContextMenu = (e: MouseEvent, target?: { row: number; col: number }) =
const rowRefs = $ref<any[]>() const rowRefs = $ref<any[]>()
/** save/update records before unmounting the component */ const saveOrUpdateRecords = async (args: { metaValue?: TableType; viewMetaValue?: ViewType; data?: any } = {}) => {
onBeforeUnmount(async () => {
let index = -1 let index = -1
for (const currentRow of data.value) { for (const currentRow of args.data || data.value) {
index++ index++
/** if new record save row and save the LTAR cells */ /** if new record save row and save the LTAR cells */
if (currentRow.rowMeta.new) { if (currentRow.rowMeta.new) {
const syncLTARRefs = rowRefs[index]!.syncLTARRefs const syncLTARRefs = rowRefs[index]!.syncLTARRefs
const savedRow = await updateOrSaveRow(currentRow, '') const savedRow = await updateOrSaveRow(currentRow, '', {}, args)
await syncLTARRefs(savedRow) await syncLTARRefs(savedRow, args)
currentRow.rowMeta.changed = false currentRow.rowMeta.changed = false
continue continue
} }
/** if existing row check updated cell and invoke update method */ /** if existing row check updated cell and invoke update method */
if (currentRow.rowMeta.changed) { if (currentRow.rowMeta.changed) {
currentRow.rowMeta.changed = false 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 (isVirtualCol(field)) continue
if (currentRow.row[field.title!] !== currentRow.oldRow[field.title!]) { 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({ const expandedFormOnRowIdDlg = computed({
@ -320,9 +330,21 @@ provide(ReloadRowDataHookInj, reloadViewDataHook)
// reloadViewDataHook.trigger() // reloadViewDataHook.trigger()
watch( watch(
() => view.value?.id, view,
async (next, old) => { 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() 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 { try {
await $api.dbTableRow.nestedAdd( await $api.dbTableRow.nestedAdd(
NOCO, NOCO,
project.value.title as string, project.value.title as string,
meta.value?.title as string, metaValue?.title as string,
rowId, rowId,
type as 'mm' | 'hm', type as 'mm' | 'hm',
column.title as string, column.title as string,
@ -82,9 +88,9 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState(
} }
/** sync LTAR relations kept in local state */ /** sync LTAR relations kept in local state */
const syncLTARRefs = async (row: Record<string, any>) => { const syncLTARRefs = async (row: Record<string, any>, { metaValue = meta.value }: { metaValue?: TableType } = {}) => {
const id = extractPkFromRow(row, meta.value?.columns as ColumnType[]) const id = extractPkFromRow(row, metaValue?.columns as ColumnType[])
for (const column of meta?.value?.columns ?? []) { for (const column of metaValue?.columns ?? []) {
if (column.uidt !== UITypes.LinkToAnotherRecord) continue if (column.uidt !== UITypes.LinkToAnotherRecord) continue
const colOptions = column?.colOptions as LinkToAnotherRecordType const colOptions = column?.colOptions as LinkToAnotherRecordType
@ -99,6 +105,7 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState(
extractPkFromRow(relatedRow, relatedTableMeta.columns as ColumnType[]), extractPkFromRow(relatedRow, relatedTableMeta.columns as ColumnType[]),
column, column,
colOptions.type as RelationTypes, colOptions.type as RelationTypes,
{ metaValue },
) )
} }
} else if (isBt && state?.value?.[column.title!]) { } 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[]), extractPkFromRow(state.value?.[column.title!] as Record<string, any>, relatedTableMeta.columns as ColumnType[]),
column, column,
colOptions.type as RelationTypes, colOptions.type as RelationTypes,
{ metaValue },
) )
} }
} }

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

@ -200,12 +200,13 @@ export function useViewData(
row: Record<string, any>, row: Record<string, any>,
rowIndex = formattedData.value?.length, rowIndex = formattedData.value?.length,
ltarState: Record<string, any> = {}, ltarState: Record<string, any> = {},
{ metaValue = meta.value, viewMetaValue = viewMeta.value }: { metaValue?: TableType; viewMetaValue?: ViewType } = {},
) { ) {
try { try {
const { getMeta } = useMetas() const { getMeta } = useMetas()
const { missingRequiredColumns, insertObj } = await populateInsertObject({ const { missingRequiredColumns, insertObj } = await populateInsertObject({
meta: meta.value!, meta: metaValue!,
ltarState, ltarState,
getMeta, getMeta,
row, row,
@ -216,8 +217,8 @@ export function useViewData(
const insertedData = await $api.dbViewRow.create( const insertedData = await $api.dbViewRow.create(
NOCO, NOCO,
project?.value.id as string, project?.value.id as string,
meta.value?.id as string, metaValue?.id as string,
viewMeta?.value?.id as string, viewMetaValue?.id as string,
insertObj, 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 { try {
const id = extractPkFromRow(toUpdate.row, meta.value?.columns as ColumnType[]) const id = extractPkFromRow(toUpdate.row, meta.value?.columns as ColumnType[])
const updatedRowData = await $api.dbViewRow.update( const updatedRowData = await $api.dbViewRow.update(
NOCO, NOCO,
project?.value.id as string, project?.value.id as string,
meta.value?.id as string, metaValue?.id as string,
viewMeta?.value?.id as string, viewMetaValue?.id as string,
id, id,
{ {
[property]: toUpdate.row[property], [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) { 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 { } else {
await updateRowProperty(row, property!) await updateRowProperty(row, property!, args)
} }
} }

Loading…
Cancel
Save