Browse Source

feat(gui-v2): add save/update action

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/3025/head
Pranav C 2 years ago
parent
commit
c0a12602be
  1. 18
      packages/nc-gui-v2/components/smartsheet/expanded-form/Header.vue
  2. 5
      packages/nc-gui-v2/components/smartsheet/expanded-form/index.vue
  3. 274
      packages/nc-gui-v2/composables/useExpandedFormStore.ts

18
packages/nc-gui-v2/components/smartsheet/expanded-form/Header.vue

@ -1,24 +1,22 @@
<script lang="ts" setup>
import { computed } from '#imports'
import { useExpandedFormStoreOrThrow, useSmartsheetStoreOrThrow, useUIPermission } from '#imports'
import { computed, useExpandedFormStoreOrThrow, useSmartsheetStoreOrThrow, useUIPermission } from '#imports'
import MdiDoorOpen from '~icons/mdi/door-open'
import MdiDoorClosed from '~icons/mdi/door-closed'
const {meta} = useSmartsheetStoreOrThrow()
const { meta } = useSmartsheetStoreOrThrow()
const { commentsDrawer, row, primaryValue, save } = useExpandedFormStoreOrThrow()
const { isUIAllowed} =useUIPermission()
const { isUIAllowed } = useUIPermission()
const drawerToggleIcon = computed(() => (commentsDrawer.value ? MdiDoorOpen : MdiDoorClosed))
// todo: accept as a prop / inject
const iconColor = '#1890ff'
const iconColor = '#1890ff'
</script>
<template>
<div class="flex p-2 align-center gap-2">
<h5 class="text-md font-weight-bold flex align-center gap-1 mb-0">
<mdi-table-arrow-right :style="{color:iconColor}"/>
<h5 class="text-lg font-weight-medium flex align-center gap-1 mb-0">
<mdi-table-arrow-right :style="{ color: iconColor }" />
<template v-if="meta">
{{ meta.title }}
@ -29,14 +27,14 @@ const iconColor = '#1890ff'
<template v-if="primaryValue">: {{ primaryValue }}</template>
</h5>
<div class="flex-grow" />
<mdi-reload/>
<mdi-reload />
<component :is="drawerToggleIcon" class="" @click="commentsDrawer = !commentsDrawer" />
<a-button size="small" class="!text">
<!-- Cancel -->
{{ $t('general.cancel') }}
</a-button>
<a-button size="small" :disabled="!isUIAllowed('tableRowUpdate')" type="primary" @click="save">
<!--Save Row-->
<!-- Save Row -->
{{ $t('activity.saveRow') }}
</a-button>
</div>

5
packages/nc-gui-v2/components/smartsheet/expanded-form/index.vue

@ -26,7 +26,7 @@ provide(IsFormInj, true)
// accept as a prop
// const row: Row = { row: {}, rowMeta: {}, oldRow: {} }
const { loadComments, commentsDrawer } = useProvideExpandedFormStore(meta, row)
const { commentsDrawer, changedColumns } = useProvideExpandedFormStore(meta, row)
const isExpanded = useVModel(props, 'modelValue', emits)
</script>
@ -49,8 +49,7 @@ const isExpanded = useVModel(props, 'modelValue', emits)
v-model="row.row[col.title]"
:column="col"
:edit-enabled="true"
@update:edit-enabled="editEnabled = false"
@cancel="editEnabled = false"
@update:modelValue="changedColumns.push(col.title)"
/>
</div>
</div>

274
packages/nc-gui-v2/composables/useExpandedFormStore.ts

@ -1,130 +1,198 @@
import { UITypes } from 'nocodb-sdk'
import type { ColumnType, TableType } from 'nocodb-sdk'
import type { Ref } from 'vue'
import { message } from 'ant-design-vue'
import { message, notification } from 'ant-design-vue'
import dayjs from 'dayjs'
import { NOCO } from '~/lib'
import getPlainText from '../../nc-gui/components/project/spreadsheet/helpers/getPlainText'
import { useNuxtApp } from '#app'
import { useInjectionState } from '#imports'
import { useApi } from '~/composables/useApi'
import { useViewData } from '~/composables/useViewData'
import type { Row } from '~/composables/useViewData'
import { ActiveViewInj } from '~/context'
import { extractPkFromRow } from '~/utils'
import dayjs from 'dayjs'
const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState(
(meta: Ref<TableType>, row: Ref<Record<string, any>>) => {
const { $e, $state } = useNuxtApp()
const { api, isLoading: isCommentsLoading, error: commentsError } = useApi()
// { useGlobalInstance: true },
// state
const commentsOnly = ref(false)
const commentsAndLogs = ref([])
const comment = ref('')
const commentsDrawer = ref(false)
// todo
const activeView = inject(ActiveViewInj)
const { updateOrSaveRow, insertRow } = useViewData(meta, activeView as any)
// getters
const primaryValue = computed(() => {
if (row?.value?.row) {
const col = meta?.value?.columns?.find(c => c.pv)
if (!col) {
return
import { extractPkFromRow, extractSdkResponseErrorMsg } from '~/utils'
const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((meta: Ref<TableType>, row: Ref<Row>) => {
const { $e, $state, $api } = useNuxtApp()
const { api, isLoading: isCommentsLoading, error: commentsError } = useApi()
// { useGlobalInstance: true },
// state
const commentsOnly = ref(false)
const commentsAndLogs = ref([])
const comment = ref('')
const commentsDrawer = ref(false)
const changedColumns = reactive(new Set<string>())
const { project } = useProject()
// todo
// const activeView = inject(ActiveViewInj)
// const { updateOrSaveRow, insertRow } = useViewData(meta, activeView as any)
// getters
const primaryValue = computed(() => {
if (row?.value?.row) {
const col = meta?.value?.columns?.find((c) => c.pv)
if (!col) {
return
}
const value = row.value.row?.[col.title as string]
const uidt = col.uidt
if (uidt === UITypes.Date) {
return (/^\d+$/.test(value) ? dayjs(+value) : dayjs(value)).format('YYYY-MM-DD')
} else if (uidt === UITypes.DateTime) {
return (/^\d+$/.test(value) ? dayjs(+value) : dayjs(value)).format('YYYY-MM-DD HH:mm')
} else if (uidt === UITypes.Time) {
let dateTime = dayjs(value)
if (!dateTime.isValid()) {
dateTime = dayjs(value, 'HH:mm:ss')
}
if (!dateTime.isValid()) {
dateTime = dayjs(`1999-01-01 ${value}`)
}
const value = row.value.row?.[col.title as string]
const uidt = col.uidt
if (uidt === UITypes.Date) {
return (/^\d+$/.test(value) ? dayjs(+value) : dayjs(value)).format('YYYY-MM-DD')
} else if (uidt === UITypes.DateTime) {
return (/^\d+$/.test(value) ? dayjs(+value) : dayjs(value)).format('YYYY-MM-DD HH:mm')
} else if (uidt === UITypes.Time) {
let dateTime = dayjs(value)
if (!dateTime.isValid()) {
dateTime = dayjs(value, 'HH:mm:ss')
}
if (!dateTime.isValid()) {
dateTime = dayjs(`1999-01-01 ${value}`)
}
if (!dateTime.isValid()) {
return value
}
return dateTime.format('HH:mm:ss')
if (!dateTime.isValid()) {
return value
}
return value
return dateTime.format('HH:mm:ss')
}
})
return value
}
})
// actions
const loadCommentsAndLogs = async () => {
if (!row.value) return
const rowId = extractPkFromRow(row.value.row, meta.value.columns as ColumnType[])
if (!rowId) return
commentsAndLogs.value =
(
await api.utils.commentList({
row_id: rowId,
fk_model_id: meta.value.id as string,
comments_only: commentsOnly.value,
})
)?.reverse?.() || []
}
const isYou = (email:string) => {
return $state.user?.value?.email === email
}
// actions
const loadCommentsAndLogs = async () => {
if (!row.value) return
const saveComment = async () => {
try {
if (!row.value || !comment.value) return
const rowId = extractPkFromRow(row.value.row, meta.value.columns as ColumnType[])
if (!rowId) return
commentsAndLogs.value =
(
await api.utils.commentList({
row_id: rowId,
fk_model_id: meta.value.id as string,
comments_only: commentsOnly.value,
})
)?.reverse?.() || []
}
const isYou = (email) => {
return $state.user?.value?.email === email
await api.utils.commentRow({
fk_model_id: meta.value?.id as string,
row_id: rowId,
description: comment.value,
})
comment.value = ''
message.success('Comment added successfully')
await loadCommentsAndLogs()
} catch (e: any) {
message.error(e.message)
}
const saveComment = async () => {
try {
if (!row.value || !comment.value) return
const rowId = extractPkFromRow(row.value.row, meta.value.columns as ColumnType[])
if (!rowId) return
$e('a:row-expand:comment')
}
const save = async () => {
try {
// todo:
// if (this.presetValues) {
// // cater presetValues
// for (const k in this.presetValues) {
// this.$set(this.changedColumns, k, true);
// }
// }
const updateOrInsertObj = [...changedColumns].reduce((obj, col) => {
obj[col] = row.value.row[col]
return obj
}, {} as Record<string, any>)
if (row.value.rowMeta.new) {
const data = await $api.dbTableRow.create('noco', project.value.title as string, meta.value.title, updateOrInsertObj)
/* todo:
// save hasmany and manytomany relations from local state
if (this.$refs.virtual && Array.isArray(this.$refs.virtual)) {
for (const vcell of this.$refs.virtual) {
if (vcell.save) {
await vcell.save(this.localState);
}
}
} */
row.value = {
row: data,
rowMeta: {},
oldRow: { ...data },
}
await api.utils.commentRow({
fk_model_id: meta.value?.id as string,
row_id: rowId,
description: comment.value,
})
/// todo:
// await this.reload();
} else if (Object.keys(updateOrInsertObj).length) {
const id = extractPkFromRow(row.value.row, meta.value.columns as ColumnType[])
comment.value = ''
message.success('Comment added successfully')
await loadCommentsAndLogs()
} catch (e: any) {
message.error(e.message)
if (!id) {
return message.info("Update not allowed for table which doesn't have primary Key")
}
await $api.dbTableRow.update(NOCO, project.value.title as string, meta.value.title, id, updateOrInsertObj)
for (const key of Object.keys(updateOrInsertObj)) {
// audit
$api.utils
.auditRowUpdate(id, {
fk_model_id: meta.value.id,
column_name: key,
row_id: id,
value: getPlainText(updateOrInsertObj[key]),
prev_value: getPlainText(row.value.oldRow[key]),
})
.then(() => {
})
}
} else {
return message.info('No columns to update')
}
$e('a:row-expand:comment')
}
const save = async () => {
// try {
// await updateOrSaveRow(row.value.row)
// message.success('Saved successfully')
// } catch (e: any) {
// message.error(e.message)
// }
}
// this.$emit('update:oldRow', { ...this.localState });
// this.changedColumns = {};
// this.$emit('input', this.localState);
// this.$emit('update:isNew', false);
notification.success({
message: `${this.primaryValue() || 'Row'} updated successfully.`,
// position: 'bottom-right',
})
return {
commentsOnly,
loadCommentsAndLogs,
commentsAndLogs,
isCommentsLoading,
commentsError,
saveComment,
comment,
isYou,
commentsDrawer,
row,
primaryValue, save,
changedColumns.clear()
} catch (e: any) {
notification.error({ message: `Failed to update row`, description: await extractSdkResponseErrorMsg(e) })
}
},
'expanded-form-store',
)
$e('a:row-expand:add')
}
return {
commentsOnly,
loadCommentsAndLogs,
commentsAndLogs,
isCommentsLoading,
commentsError,
saveComment,
comment,
isYou,
commentsDrawer,
row,
primaryValue,
save,
changedColumns,
}
}, 'expanded-form-store')
export { useProvideExpandedFormStore }

Loading…
Cancel
Save