Browse Source

feat(gui-v2): keep row level state

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/3025/head
Pranav C 2 years ago
parent
commit
56dca1166a
  1. 2
      packages/nc-gui-v2/components.d.ts
  2. 9
      packages/nc-gui-v2/components/smartsheet/Grid.vue
  3. 79
      packages/nc-gui-v2/components/smartsheet/Row.vue
  4. 1
      packages/nc-gui-v2/components/smartsheet/expanded-form/index.vue
  5. 2
      packages/nc-gui-v2/components/virtual-cell/HasMany.vue
  6. 14
      packages/nc-gui-v2/composables/useExpandedFormStore.ts
  7. 28
      packages/nc-gui-v2/composables/useSmartsheetRowStore.ts

2
packages/nc-gui-v2/components.d.ts vendored

@ -80,6 +80,8 @@ declare module '@vue/runtime-core' {
MdiApi: typeof import('~icons/mdi/api')['default'] MdiApi: typeof import('~icons/mdi/api')['default']
MdiArrowExpand: typeof import('~icons/mdi/arrow-expand')['default'] MdiArrowExpand: typeof import('~icons/mdi/arrow-expand')['default']
MdiArrowLeftBold: typeof import('~icons/mdi/arrow-left-bold')['default'] MdiArrowLeftBold: typeof import('~icons/mdi/arrow-left-bold')['default']
MdiArrowExpand: typeof import('~icons/mdi/arrow-expand')['default']
MdiArrowExpandIcon: typeof import('~icons/mdi/arrow-expand-icon')['default']
MdiAt: typeof import('~icons/mdi/at')['default'] MdiAt: typeof import('~icons/mdi/at')['default']
MdiCalculator: typeof import('~icons/mdi/calculator')['default'] MdiCalculator: typeof import('~icons/mdi/calculator')['default']
MdiCardsHeart: typeof import('~icons/mdi/cards-heart')['default'] MdiCardsHeart: typeof import('~icons/mdi/cards-heart')['default']

9
packages/nc-gui-v2/components/smartsheet/Grid.vue

@ -329,6 +329,14 @@ const expandForm = (row: Row) => {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<SmartsheetRow
v-for="(row, rowIndex) in data"
:key="row.id"
:row="row"
:row-index="rowIndex"
:selected="selected"
:edit-enabled="editEnabled"
>
<tr v-for="(row, rowIndex) of data" :key="rowIndex" class="nc-grid-row"> <tr v-for="(row, rowIndex) of data" :key="rowIndex" class="nc-grid-row">
<td key="row-index" class="caption nc-grid-cell group"> <td key="row-index" class="caption nc-grid-cell group">
<div class="flex items-center w-[80px]"> <div class="flex items-center w-[80px]">
@ -388,6 +396,7 @@ const expandForm = (row: Row) => {
</div> </div>
</td> </td>
</tr> </tr>
</SmartsheetRow>
<tr v-if="!isLocked"> <tr v-if="!isLocked">
<td <td

79
packages/nc-gui-v2/components/smartsheet/Row.vue

@ -0,0 +1,79 @@
<script lang="ts" setup>
import { isVirtualCol } from 'nocodb-sdk'
import type { Row } from '~/composables'
import { useSmartsheetStoreOrThrow } from '~/composables'
import { useProvideSmartsheetRowStore } from '~/composables/useSmartsheetRowStore'
import { FieldsInj } from '~/context'
interface Props {
row: Row
selected: { col?: number; row?: number }
rowIndex: number
editEnabled: boolean
}
const props = defineProps<Props>()
const emit = defineEmits(['expandForm', 'selectCell', 'updateOrSaveRow', 'navigate'])
const row = toRef(props, 'row')
const rowIndex = toRef(props, 'rowIndex')
const editEnabled = toRef(props, 'editEnabled')
// todo : from props / inject
const isPublicView = false
const fields = inject(FieldsInj, ref([]))
const { meta } = useSmartsheetStoreOrThrow()
const { isNew } = useProvideSmartsheetRowStore(meta, row)
</script>
<template>
<tr class="nc-grid-row group">
<td key="row-index" class="caption nc-grid-cell">
<div class="align-center flex w-[80px]">
<div class="group-hover:hidden" :class="{ hidden: row.rowMeta.selected }">{{ rowIndex + 1 }}</div>
<div :class="{ hidden: !row.rowMeta.selected, flex: row.rowMeta.selected }" class="group-hover:flex w-full align-center">
<a-checkbox v-model:checked="row.rowMeta.selected" />
<span class="flex-1" />
<mdi-arrow-expand class="text-sm text-pink hidden group-hover:inline-block" @click="emit('expandForm')" />
</div>
</div>
</td>
<td
v-for="(columnObj, colIndex) in fields"
:key="columnObj.title"
class="cell pointer nc-grid-cell"
:class="{
active: !isPublicView && selected.col === colIndex && selected.row === rowIndex,
}"
:data-col="columnObj.id"
@click="emit('selectCell', rowIndex, colIndex)"
@dblclick="editEnabled = true"
@contextmenu="contextMenuTarget = { row: rowIndex, col: colIndex }"
>
<div class="w-full h-full">
<SmartsheetVirtualCell
v-if="isVirtualCol(columnObj)"
v-model="row.row[columnObj.title]"
:column="columnObj"
:active="selected.col === colIndex && selected.row === rowIndex"
:row="row"
@navigate="emit('navigate', $event)"
/>
<SmartsheetCell
v-else
v-model="row.row[columnObj.title]"
:column="columnObj"
:edit-enabled="editEnabled && selected.col === colIndex && selected.row === rowIndex"
@update:edit-enabled="editEnabled = false"
@save="emit('updateOrSaveRow', row, columnObj.title)"
@navigate="emit('navigate', $event)"
@cancel="emit('cancel')"
/>
</div>
</td>
</tr>
</template>

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

@ -43,7 +43,6 @@ const isExpanded = useVModel(props, 'modelValue', emits)
<SmartsheetHeaderCell v-else :column="col" /> <SmartsheetHeaderCell v-else :column="col" />
<div class="!bg-white rounded px-1 min-h-[35px] flex align-center"> <div class="!bg-white rounded px-1 min-h-[35px] flex align-center">
<SmartsheetVirtualCell v-if="isVirtualCol(col)" v-model="row.row[col.title]" :row="row" :column="col" /> <SmartsheetVirtualCell v-if="isVirtualCol(col)" v-model="row.row[col.title]" :row="row" :column="col" />
<SmartsheetCell <SmartsheetCell
v-else v-else

2
packages/nc-gui-v2/components/virtual-cell/HasMany.vue

@ -4,6 +4,7 @@ import type { Ref } from 'vue'
import ItemChip from './components/ItemChip.vue' import ItemChip from './components/ItemChip.vue'
import ListChildItems from './components/ListChildItems.vue' import ListChildItems from './components/ListChildItems.vue'
import ListItems from './components/ListItems.vue' import ListItems from './components/ListItems.vue'
import { useProvideSmartsheetRowStore, useSmartsheetRowStoreOrThrow } from '~/composables/useSmartsheetRowStore'
import { computed, inject, ref, useProvideLTARStore } from '#imports' import { computed, inject, ref, useProvideLTARStore } from '#imports'
import { CellValueInj, ColumnInj, IsFormInj, ReloadViewDataHookInj, RowInj } from '~/context' import { CellValueInj, ColumnInj, IsFormInj, ReloadViewDataHookInj, RowInj } from '~/context'
@ -26,6 +27,7 @@ const listItemsDlg = ref(false)
const childListDlg = ref(false) const childListDlg = ref(false)
const { localState, isNew } = useSmartsheetRowStoreOrThrow()
const { loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore( const { loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore(
column as Ref<Required<ColumnType>>, column as Ref<Required<ColumnType>>,
row, row,

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

@ -3,15 +3,16 @@ import type { ColumnType, TableType } from 'nocodb-sdk'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { message, notification } from 'ant-design-vue' import { message, notification } from 'ant-design-vue'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { NOCO } from '~/lib'
import getPlainText from '../../nc-gui/components/project/spreadsheet/helpers/getPlainText' import getPlainText from '../../nc-gui/components/project/spreadsheet/helpers/getPlainText'
import { useProvideSmartsheetRowStore } from '~/composables/useSmartsheetRowStore'
import { NOCO } from '~/lib'
import { useNuxtApp } from '#app' import { useNuxtApp } from '#app'
import { useInjectionState,useProject } from '#imports' import { useInjectionState, useProject } from '#imports'
import { useApi } from '~/composables/useApi' import { useApi } from '~/composables/useApi'
import type { Row } from '~/composables/useViewData' import type { Row } from '~/composables/useViewData'
import { extractPkFromRow, extractSdkResponseErrorMsg } from '~/utils' import { extractPkFromRow, extractSdkResponseErrorMsg } from '~/utils'
const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((meta: Ref<TableType>, row: Ref<Row>, ) => { const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((meta: Ref<TableType>, row: Ref<Row>) => {
const { $e, $state, $api } = useNuxtApp() const { $e, $state, $api } = useNuxtApp()
const { api, isLoading: isCommentsLoading, error: commentsError } = useApi() const { api, isLoading: isCommentsLoading, error: commentsError } = useApi()
// { useGlobalInstance: true }, // { useGlobalInstance: true },
@ -22,6 +23,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
const commentsDrawer = ref(false) const commentsDrawer = ref(false)
const changedColumns = ref(new Set<string>()) const changedColumns = ref(new Set<string>())
const { project } = useProject() const { project } = useProject()
const rowStore = useProvideSmartsheetRowStore(meta, row)
// todo // todo
// const activeView = inject(ActiveViewInj) // const activeView = inject(ActiveViewInj)
@ -72,7 +74,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
)?.reverse?.() || [] )?.reverse?.() || []
} }
const isYou = (email:string) => { const isYou = (email: string) => {
return $state.user?.value?.email === email return $state.user?.value?.email === email
} }
@ -151,8 +153,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
value: getPlainText(updateOrInsertObj[key]), value: getPlainText(updateOrInsertObj[key]),
prev_value: getPlainText(row.value.oldRow[key]), prev_value: getPlainText(row.value.oldRow[key]),
}) })
.then(() => { .then(() => {})
})
} }
} else { } else {
return message.info('No columns to update') return message.info('No columns to update')
@ -176,6 +177,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
} }
return { return {
...rowStore,
commentsOnly, commentsOnly,
loadCommentsAndLogs, loadCommentsAndLogs,
commentsAndLogs, commentsAndLogs,

28
packages/nc-gui-v2/composables/useSmartsheetRowStore.ts

@ -0,0 +1,28 @@
import type { TableType } from 'nocodb-sdk'
import type { Ref } from 'vue'
import { useInjectionState } from '#imports'
import type { Row } from '~/composables/useViewData'
const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState((meta: Ref<TableType>, row: Ref<Row>) => {
// state
const localState = reactive({})
// getters
const isNew = computed(() => row.value?.rowMeta?.new)
// actions
return {
row,
localState,
isNew,
}
}, 'smartsheet-row-store')
export { useProvideSmartsheetRowStore }
export function useSmartsheetRowStoreOrThrow() {
const smartsheetRowStore = useSmartsheetRowStore()
if (smartsheetRowStore == null) throw new Error('Please call `useSmartsheetRowStore` on the appropriate parent component')
return smartsheetRowStore
}
Loading…
Cancel
Save