From c2d028ec798167b70573d742d2f0eb2980278b85 Mon Sep 17 00:00:00 2001 From: mertmit Date: Wed, 14 Jun 2023 18:59:00 +0300 Subject: [PATCH 01/24] feat: vertical fill using handle Signed-off-by: mertmit --- .../nc-gui/components/smartsheet/Grid.vue | 103 ++++++++- .../components/smartsheet/TableDataCell.vue | 2 + .../composables/useMultiSelect/index.ts | 217 ++++++++++++++---- 3 files changed, 277 insertions(+), 45 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/Grid.vue b/packages/nc-gui/components/smartsheet/Grid.vue index 659fe932e8..24bba4ec2f 100644 --- a/packages/nc-gui/components/smartsheet/Grid.vue +++ b/packages/nc-gui/components/smartsheet/Grid.vue @@ -2,6 +2,7 @@ import { nextTick } from '@vue/runtime-core' import type { ColumnReqType, ColumnType, GridType, PaginatedType, TableType, ViewType } from 'nocodb-sdk' import { UITypes, isSystemColumn, isVirtualCol } from 'nocodb-sdk' +import type { UseElementBoundingReturn } from '@vueuse/core' import { ActiveViewInj, CellUrlDisableOverlayInj, @@ -109,6 +110,7 @@ const expandedFormRowState = ref>() const gridWrapper = ref() const tableHeadEl = ref() const tableBodyEl = ref() +const fillHandle = ref() const isAddingColumnAllowed = $computed(() => !readOnly.value && !isLocked.value && isUIAllowed('add-column') && !isSqlView.value) @@ -207,6 +209,7 @@ const { resetSelectedRange, makeActive, selectedRange, + isCellInFillRange, } = useMultiSelect( meta, fields, @@ -348,6 +351,7 @@ const { await updateOrSaveRow(rowObj, ctx.updatedColumnTitle || columnObj.title) }, bulkUpdateRows, + fillHandle, ) function scrollToCell(row?: number | null, col?: number | null) { @@ -650,9 +654,9 @@ useEventListener(document, 'keyup', async (e: KeyboardEvent) => { } }) -/** On clicking outside of table reset active cell */ const smartTable = ref(null) +/** On clicking outside of table reset active cell */ onClickOutside(tableBodyEl, (e) => { // do nothing if context menu was open if (contextMenu.value) return @@ -666,7 +670,7 @@ onClickOutside(tableBodyEl, (e) => { // ignore unselecting if clicked inside or on the picker(Date, Time, DateTime, Year) // or single/multi select options const activePickerOrDropdownEl = document.querySelector( - '.nc-picker-datetime.active,.nc-dropdown-single-select-cell.active,.nc-dropdown-multi-select-cell.active,.nc-picker-date.active,.nc-picker-year.active,.nc-picker-time.active', + '.nc-picker-datetime.active,.nc-dropdown-single-select-cell.active,.nc-dropdown-multi-select-cell.active,.nc-picker-date.active,.nc-picker-year.active,.nc-picker-time.active,.nc-fill-handle', ) if ( e.target && @@ -881,10 +885,51 @@ function addEmptyRow(row?: number) { nextTick().then(() => { clearSelectedRange() makeActive(row ?? data.value.length - 1, 0) + selectedRange.startRange({ row: activeCell.row!, col: activeCell.col! }) scrollToCell?.() }) return rowObj } + +const tableRect = useElementBounding(smartTable) +const { height: tableHeight, width: tableWidth } = tableRect + +const { x: gridX, y: gridY } = useScroll(gridWrapper) + +const fillHandleTop = ref() +const fillHandleLeft = ref() + +const cellRefs = ref<{ el: HTMLElement }[]>([]) +let cellRect: UseElementBoundingReturn | null = null + +const refreshFillHandle = () => { + const cellRef = cellRefs.value.find( + (cell) => + cell.el.dataset.rowIndex === String(selectedRange.end.row) && cell.el.dataset.colIndex === String(selectedRange.end.col), + ) + if (cellRef) { + cellRect = useElementBounding(cellRef.el) + if (!cellRect || !tableRect) return + if (selectedRange.end.col === 0) { + fillHandleTop.value = cellRect.top.value - tableRect.top.value + cellRect.height.value - 4.5 + gridY.value + fillHandleLeft.value = cellRect.left.value - tableRect.left.value + cellRect.width.value - 4.5 + return + } + fillHandleTop.value = cellRect.top.value - tableRect.top.value + cellRect.height.value - 4.5 + gridY.value + fillHandleLeft.value = cellRect.left.value - tableRect.left.value + cellRect.width.value - 4.5 + gridX.value + } +} + +watch( + () => `${selectedRange.end.row}-${selectedRange.end.col}`, + (n, o) => { + if (n !== o) { + if (gridWrapper.value) { + refreshFillHandle() + } + } + }, +) +
+ +
+