Browse Source

fix(gui): save row on switching tables

Signed-off-by: Pranav C <pranavxc@gmail.com>
fix/save-rows-on-tab-switch
Pranav C 2 years ago
parent
commit
ff13ea4c51
  1. 14
      packages/nc-gui/components/smartsheet/Cell.vue
  2. 26
      packages/nc-gui/components/smartsheet/Grid.vue
  3. 3
      packages/nc-gui/components/smartsheet/Row.vue
  4. 15
      packages/nc-gui/components/tabs/Smartsheet.vue
  5. 3
      packages/nc-gui/composables/useSmartsheetRowStore.ts
  6. 15
      packages/nc-gui/composables/useViewData.ts
  7. 10
      packages/nc-gui/pages/[projectType]/[projectId]/index/index/[type]/[title]/[[viewTitle]].vue

14
packages/nc-gui/components/smartsheet/Cell.vue

@ -17,6 +17,7 @@ import {
useDebounceFn, useDebounceFn,
useVModel, useVModel,
} from '#imports' } from '#imports'
import { useSmartsheetRowStoreOrThrow } from '~/composables/useSmartsheetRowStore'
import { NavigateDir } from '~/lib' import { NavigateDir } from '~/lib'
interface Props { interface Props {
@ -57,13 +58,14 @@ const isPublic = inject(IsPublicInj, ref(false))
const isLocked = inject(IsLockedInj, ref(false)) const isLocked = inject(IsLockedInj, ref(false))
let changed = $ref(false) const { currentRow } = useSmartsheetRowStoreOrThrow()
const syncValue = useDebounceFn(function () { const syncValue = useDebounceFn(function () {
changed = false currentRow.value.rowMeta.changed = false
emit('save') emit('save')
}, 1000) }, 1000)
const isAutoSaved = $computed(() => { const isAutoSaved = $computed(() => {
return [ return [
UITypes.SingleLineText, UITypes.SingleLineText,
@ -89,13 +91,13 @@ const vModel = computed({
get: () => props.modelValue, get: () => props.modelValue,
set: (val) => { set: (val) => {
if (val !== props.modelValue) { if (val !== props.modelValue) {
changed = true currentRow.value.rowMeta.changed = true
emit('update:modelValue', val) emit('update:modelValue', val)
if (isAutoSaved) { if (isAutoSaved) {
syncValue() syncValue()
} else if (!isManualSaved) { } else if (!isManualSaved) {
emit('save') emit('save')
changed = true currentRow.value.rowMeta.changed = true
} }
} }
}, },
@ -129,9 +131,9 @@ const {
const syncAndNavigate = (dir: NavigateDir) => { const syncAndNavigate = (dir: NavigateDir) => {
if (isJSON.value) return if (isJSON.value) return
if (changed) { if (currentRow.value.rowMeta.changed) {
emit('save') emit('save')
changed = false currentRow.value.rowMeta.changed = false
} }
emit('navigate', dir) emit('navigate', dir)
} }

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

@ -248,8 +248,7 @@ const onKeyDown = async (e: KeyboardEvent) => {
e.preventDefault() e.preventDefault()
if (selected.row < data.value.length - 1) selected.row++ if (selected.row < data.value.length - 1) selected.row++
break break
default: default: {
{
const rowObj = data.value[selected.row] const rowObj = data.value[selected.row]
const columnObj = fields.value[selected.col] const columnObj = fields.value[selected.col]
@ -324,6 +323,26 @@ const showContextMenu = (e: MouseEvent, target?: { row: number; col: number }) =
contextMenuTarget.value = target contextMenuTarget.value = target
} }
} }
onBeforeUnmount(async () => {
for (const row of data.value) {
if (row.rowMeta.new) {
await updateOrSaveRow(row, null)
row.rowMeta.changed = false
continue
}
if (row.rowMeta.changed) {
row.rowMeta.changed = false
for (const field of meta?.value.columns ?? []) {
if (isVirtualCol(field)) continue
if (row.row[field.title!] !== row.oldRow[field.title!]) {
await updateOrSaveRow(row, field.title!)
}
}
}
}
})
</script> </script>
<template> <template>
@ -419,7 +438,8 @@ const showContextMenu = (e: MouseEvent, target?: { row: number; col: number }) =
<a-checkbox v-model:checked="row.rowMeta.selected" /> <a-checkbox v-model:checked="row.rowMeta.selected" />
</div> </div>
<span class="flex-1" /> <span class="flex-1" />
<div v-if="!readOnly && !isLocked" class="nc-expand" :class="{ 'nc-comment': row.rowMeta?.commentCount }"> <div v-if="!readOnly && !isLocked" class="nc-expand"
:class="{ 'nc-comment': row.rowMeta?.commentCount }">
<span <span
v-if="row.rowMeta?.commentCount" v-if="row.rowMeta?.commentCount"
class="py-1 px-3 rounded-full text-xs cursor-pointer select-none transform hover:(scale-110)" class="py-1 px-3 rounded-full text-xs cursor-pointer select-none transform hover:(scale-110)"

3
packages/nc-gui/components/smartsheet/Row.vue

@ -1,7 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { Row } from '~/composables' import type { Row } from '~/composables'
import { useProvideSmartsheetRowStore, useSmartsheetStoreOrThrow } from '#imports' import { ReloadRowDataHookInj, useProvideSmartsheetRowStore, useSmartsheetStoreOrThrow } from '#imports'
import { ReloadRowDataHookInj } from '~/context'
interface Props { interface Props {
row: Row row: Row

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

@ -21,6 +21,11 @@ import {
import type { TabItem } from '~/composables' import type { TabItem } from '~/composables'
const { activeTab } = defineProps<{
activeTab: TabItem
}>()
const { metas } = useMetas() const { metas } = useMetas()
const activeView = ref() const activeView = ref()
@ -29,11 +34,15 @@ const el = ref<typeof SmartsheetGrid>()
const fields = ref<ColumnType[]>([]) const fields = ref<ColumnType[]>([])
const tabMeta = inject( // const tabMeta = inject(
// TabMetaInj,
// computed(() => ({} as TabItem)),
// )
provide(
TabMetaInj, TabMetaInj,
computed(() => ({} as TabItem)), ref(activeTab),
) )
const meta = computed<TableType>(() => metas.value?.[tabMeta?.value?.id as string]) const meta = computed<TableType>(() => metas.value?.[activeTab?.id as string])
const reloadEventHook = createEventHook<void>() const reloadEventHook = createEventHook<void>()
const openNewRecordFormHook = createEventHook<void>() const openNewRecordFormHook = createEventHook<void>()

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

@ -29,6 +29,8 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState(
const { metas } = useMetas() const { metas } = useMetas()
const currentRow = ref(row)
// state // state
const state = ref<Record<string, Record<string, any> | Record<string, any>[] | null>>({}) const state = ref<Record<string, Record<string, any> | Record<string, any>[] | null>>({})
@ -132,6 +134,7 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState(
removeLTARRef, removeLTARRef,
syncLTARRefs, syncLTARRefs,
loadRow, loadRow,
currentRow
} }
}, 'smartsheet-row-store') }, 'smartsheet-row-store')

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

@ -28,6 +28,7 @@ export interface Row {
new?: boolean new?: boolean
selected?: boolean selected?: boolean
commentCount?: number commentCount?: number
changed?: boolean
} }
} }
@ -210,6 +211,7 @@ export function useViewData(
await syncCount() await syncCount()
return insertedData return insertedData
} catch (error: any) { } catch (error: any) {
console.log(error)
message.error(await extractSdkResponseErrorMsg(error)) message.error(await extractSdkResponseErrorMsg(error))
} }
} }
@ -241,7 +243,8 @@ export function useViewData(
value: getHTMLEncodedText(toUpdate.row[property]), value: getHTMLEncodedText(toUpdate.row[property]),
prev_value: getHTMLEncodedText(toUpdate.oldRow[property]), prev_value: getHTMLEncodedText(toUpdate.oldRow[property]),
}) })
.then(() => {}) .then(() => {
})
/** update row data(to sync formula and other related columns) */ /** update row data(to sync formula and other related columns) */
Object.assign(toUpdate.row, updatedRowData) Object.assign(toUpdate.row, updatedRowData)
@ -267,7 +270,7 @@ export function useViewData(
async function deleteRowById(id: string) { async function deleteRowById(id: string) {
if (!id) { if (!id) {
throw new Error("Delete not allowed for table which doesn't have primary Key") throw new Error('Delete not allowed for table which doesn\'t have primary Key')
} }
const res: any = await $api.dbViewRow.delete( const res: any = await $api.dbViewRow.delete(
@ -280,11 +283,9 @@ export function useViewData(
if (res.message) { if (res.message) {
message.info( message.info(
`Row delete failed: ${h('div', { `Row delete failed: ${`Unable to delete row with ID ${id} because of the following:
innerHTML: `<div style="padding:10px 4px">Unable to delete row with ID ${id} because of the following: \n${res.message.join('\n')}.\n
<br><br>${res.message.join('<br>')}<br><br> Clear the data first & try again`})}`,
Clear the data first & try again</div>`,
})}`,
) )
return false return false
} }

10
packages/nc-gui/pages/[projectType]/[projectId]/index/index/[type]/[title]/[[viewTitle]].vue

@ -1,8 +1,16 @@
<script setup lang="ts"> <script setup lang="ts">
import { TabItem } from '~/composables'
import { TabMetaInj } from '~/context'
const { getMeta } = useMetas() const { getMeta } = useMetas()
const route = useRoute() const route = useRoute()
const loading = ref(true) const loading = ref(true)
const activeTab = inject(
TabMetaInj,
computed(() => ({} as TabItem)),
)
getMeta(route.params.title as string, true).finally(() => { getMeta(route.params.title as string, true).finally(() => {
loading.value = false loading.value = false
}) })
@ -12,7 +20,7 @@ getMeta(route.params.title as string, true).finally(() => {
<div v-if="loading" class="flex items-center justify-center h-full w-full"> <div v-if="loading" class="flex items-center justify-center h-full w-full">
<a-spin size="large" /> <a-spin size="large" />
</div> </div>
<TabsSmartsheet v-else /> <TabsSmartsheet :active-tab="activeTab" :key="route.params.title" v-else />
</template> </template>
<style scoped></style> <style scoped></style>

Loading…
Cancel
Save