Browse Source

Merge pull request #3066 from nocodb/chore/attachment-cell

chore(gui-v2): attachment cell fixes
pull/3076/head
Raju Udava 2 years ago committed by GitHub
parent
commit
acb2aadd4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      packages/nc-gui-v2/components/cell/attachment/index.vue
  2. 29
      packages/nc-gui-v2/components/smartsheet/Grid.vue
  3. 10
      packages/nc-gui-v2/composables/useSmartsheetStore.ts

25
packages/nc-gui-v2/components/cell/attachment/index.vue

@ -1,10 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { onKeyDown } from '@vueuse/core' import { onKeyDown } from '@vueuse/core'
import { useProvideAttachmentCell } from './utils' import { useProvideAttachmentCell } from './utils'
import Modal from './Modal.vue'
import { useSortable } from './sort' import { useSortable } from './sort'
import Modal from './Modal.vue'
import Carousel from './Carousel.vue' import Carousel from './Carousel.vue'
import { onMounted, ref, useDropZone, watch } from '#imports' import { computed, ref, useDropZone, useSmartsheetStoreOrThrow, watch } from '#imports'
import { isImage, openLink } from '~/utils' import { isImage, openLink } from '~/utils'
interface Props { interface Props {
@ -20,16 +20,18 @@ const { modelValue, rowIndex } = defineProps<Props>()
const emits = defineEmits<Emits>() const emits = defineEmits<Emits>()
const dropZoneRef = ref<HTMLTableDataCellElement>()
const sortableRef = ref<HTMLDivElement>() const sortableRef = ref<HTMLDivElement>()
const { cellRefs } = useSmartsheetStoreOrThrow()!
const { column, modalVisible, attachments, visibleItems, onDrop, isLoading, open, FileIcon, selectedImage, isReadonly } = const { column, modalVisible, attachments, visibleItems, onDrop, isLoading, open, FileIcon, selectedImage, isReadonly } =
useProvideAttachmentCell(updateModelValue) useProvideAttachmentCell(updateModelValue)
const currentCellRef = computed(() => cellRefs.value.find((cell) => cell.dataset.key === `${rowIndex}${column.value.id}`))
const { dragging } = useSortable(sortableRef, visibleItems, updateModelValue, isReadonly) const { dragging } = useSortable(sortableRef, visibleItems, updateModelValue, isReadonly)
const { isOverDropZone } = useDropZone(dropZoneRef, onDrop) const { isOverDropZone } = useDropZone(currentCellRef, onDrop)
/** on new value, reparse our stored attachments */ /** on new value, reparse our stored attachments */
watch( watch(
@ -52,24 +54,17 @@ onKeyDown('Escape', () => {
modalVisible.value = false modalVisible.value = false
isOverDropZone.value = false isOverDropZone.value = false
}) })
/** if possible, on mounted we try to fetch the relevant `td` cell to use as a dropzone */
onMounted(() => {
if (typeof document !== 'undefined') {
dropZoneRef.value = document.querySelector(`td[data-key="${rowIndex}${column.value.id}"]`) as HTMLTableDataCellElement
}
})
</script> </script>
<template> <template>
<div class="nc-attachment-cell relative flex-1 color-transition flex items-center justify-between gap-1"> <div class="nc-attachment-cell relative flex-1 color-transition flex items-center justify-between gap-1">
<Carousel /> <Carousel />
<template v-if="!isReadonly && !dragging && dropZoneRef"> <template v-if="!isReadonly && !dragging && !!currentCellRef">
<general-overlay <general-overlay
v-model="isOverDropZone" v-model="isOverDropZone"
inline inline
:target="`td[data-key='${rowIndex}${column.id}']`" :target="currentCellRef"
class="text-white text-lg ring ring-pink-500 bg-gray-700/75 flex items-center justify-center gap-2 backdrop-blur-xl" class="text-white text-lg ring ring-pink-500 bg-gray-700/75 flex items-center justify-center gap-2 backdrop-blur-xl"
> >
<MaterialSymbolsFileCopyOutline class="text-pink-500" /> Drop here <MaterialSymbolsFileCopyOutline class="text-pink-500" /> Drop here
@ -99,7 +94,7 @@ onMounted(() => {
<div <div
ref="sortableRef" ref="sortableRef"
:class="{ dragging }" :class="{ dragging }"
class="flex justify-center items-center flex-wrap gap-2 p-1 scrollbar-thin-dull max-h-[150px] overflow-scroll" class="flex justify-center items-center flex-wrap gap-2 p-1 scrollbar-thin-dull max-h-[150px] overflow-auto"
> >
<div <div
v-for="(item, i) of visibleItems" v-for="(item, i) of visibleItems"

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

@ -1,16 +1,20 @@
<script lang="ts" setup> <script lang="ts" setup>
import { onClickOutside, useEventListener } from '@vueuse/core'
import type { ColumnType } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import { UITypes, isVirtualCol } from 'nocodb-sdk' import { UITypes, isVirtualCol } from 'nocodb-sdk'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import { import {
inject, inject,
onClickOutside,
onMounted, onMounted,
provide, provide,
reactive,
ref,
useEventListener,
useGridViewColumnWidth, useGridViewColumnWidth,
useProvideColumnCreateStore, useProvideColumnCreateStore,
useSmartsheetStoreOrThrow, useSmartsheetStoreOrThrow,
useViewData, useViewData,
watch,
} from '#imports' } from '#imports'
import type { Row } from '~/composables' import type { Row } from '~/composables'
import { import {
@ -27,20 +31,32 @@ import {
import { NavigateDir } from '~/lib' import { NavigateDir } from '~/lib'
const meta = inject(MetaInj) const meta = inject(MetaInj)
const view = inject(ActiveViewInj) const view = inject(ActiveViewInj)
// keep a root fields variable and will get modified from // keep a root fields variable and will get modified from
// fields menu and get used in grid and gallery // fields menu and get used in grid and gallery
const fields = inject(FieldsInj, ref([])) const fields = inject(FieldsInj, ref([]))
const isLocked = inject(IsLockedInj, false) const isLocked = inject(IsLockedInj, false)
const reloadViewDataHook = inject(ReloadViewDataHookInj)
// todo: get from parent ( inject or use prop ) // todo: get from parent ( inject or use prop )
const isPublicView = false const isPublicView = false
const isView = false const isView = false
const selected = reactive<{ row: number | null; col: number | null }>({ row: null, col: null }) const selected = reactive<{ row: number | null; col: number | null }>({ row: null, col: null })
let editEnabled = $ref(false) let editEnabled = $ref(false)
const { xWhere, isPkAvail } = useSmartsheetStoreOrThrow()
const { xWhere, isPkAvail, cellRefs } = useSmartsheetStoreOrThrow()
const addColumnDropdown = ref(false) const addColumnDropdown = ref(false)
const contextMenu = ref(false) const contextMenu = ref(false)
const contextMenuTarget = ref(false) const contextMenuTarget = ref(false)
const visibleColLength = $computed(() => fields.value?.length) const visibleColLength = $computed(() => fields.value?.length)
@ -56,7 +72,9 @@ const {
deleteSelectedRows, deleteSelectedRows,
selectedAllRecords, selectedAllRecords,
} = useViewData(meta, view as any, xWhere) } = useViewData(meta, view as any, xWhere)
const { loadGridViewColumns, updateWidth, resizingColWidth, resizingCol } = useGridViewColumnWidth(view as any) const { loadGridViewColumns, updateWidth, resizingColWidth, resizingCol } = useGridViewColumnWidth(view as any)
onMounted(loadGridViewColumns) onMounted(loadGridViewColumns)
provide(IsFormInj, false) provide(IsFormInj, false)
@ -64,7 +82,6 @@ provide(IsGridInj, true)
provide(PaginationDataInj, paginationData) provide(PaginationDataInj, paginationData)
provide(ChangePageInj, changePage) provide(ChangePageInj, changePage)
const reloadViewDataHook = inject(ReloadViewDataHookInj)
reloadViewDataHook?.on(() => { reloadViewDataHook?.on(() => {
loadData() loadData()
}) })
@ -87,6 +104,7 @@ watch(
const onresize = (colID: string, event: any) => { const onresize = (colID: string, event: any) => {
updateWidth(colID, event.detail) updateWidth(colID, event.detail)
} }
const onXcResizing = (cn: string, event: any) => { const onXcResizing = (cn: string, event: any) => {
resizingCol.value = cn resizingCol.value = cn
resizingColWidth.value = event.detail resizingColWidth.value = event.detail
@ -304,7 +322,7 @@ const onNavigate = (dir: NavigateDir) => {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="(row, rowIndex) of data" :key="rowIndex" class="nc-grid-row group"> <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]">
<div class="group-hover:hidden" :class="{ hidden: row.rowMeta.selected }">{{ rowIndex + 1 }}</div> <div class="group-hover:hidden" :class="{ hidden: row.rowMeta.selected }">{{ rowIndex + 1 }}</div>
@ -322,7 +340,8 @@ const onNavigate = (dir: NavigateDir) => {
</td> </td>
<td <td
v-for="(columnObj, colIndex) of fields" v-for="(columnObj, colIndex) of fields"
:key="rowIndex + columnObj.title" :ref="cellRefs.set"
:key="columnObj.id"
class="cell relative cursor-pointer nc-grid-cell" class="cell relative cursor-pointer nc-grid-cell"
:class="{ :class="{
active: !isPublicView && selected.col === colIndex && selected.row === rowIndex, active: !isPublicView && selected.col === colIndex && selected.row === rowIndex,

10
packages/nc-gui-v2/composables/useSmartsheetStore.ts

@ -1,15 +1,14 @@
import { computed } from '@vue/reactivity'
import { ViewTypes } from 'nocodb-sdk' import { ViewTypes } from 'nocodb-sdk'
import type { TableType, ViewType } from 'nocodb-sdk' import type { TableType, ViewType } from 'nocodb-sdk'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { useNuxtApp } from '#app' import { computed, reactive, useInjectionState, useNuxtApp, useProject, useTemplateRefsList } from '#imports'
import { useProject } from '#imports'
import { useInjectionState } from '~/composables/useInjectionState'
const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState((view: Ref<ViewType>, meta: Ref<TableType>) => { const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState((view: Ref<ViewType>, meta: Ref<TableType>) => {
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const { sqlUi } = useProject() const { sqlUi } = useProject()
const cellRefs = useTemplateRefsList<HTMLTableDataCellElement>()
// state // state
// todo: move to grid view store // todo: move to grid view store
const search = reactive({ const search = reactive({
@ -37,8 +36,6 @@ const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState((view:
return where return where
}) })
// actions
return { return {
view, view,
meta, meta,
@ -50,6 +47,7 @@ const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState((view:
isForm, isForm,
isGrid, isGrid,
isGallery, isGallery,
cellRefs,
} }
}, 'smartsheet-store') }, 'smartsheet-store')

Loading…
Cancel
Save