Browse Source

Merge pull request #10016 from nocodb/nc-fix/nc-longtext-cell-focus-input-cell-issue

Nc fix/nc longtext cell focus input cell issue
pull/10015/head
Raju Udava 2 days ago committed by GitHub
parent
commit
da06438839
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      packages/nc-gui/components/cell/MultiSelect.vue
  2. 2
      packages/nc-gui/components/cell/Rating.vue
  3. 22
      packages/nc-gui/components/cell/TextArea.vue
  4. 2
      packages/nc-gui/components/cell/User.vue
  5. 20
      packages/nc-gui/components/smartsheet/grid/InfiniteTable.vue
  6. 20
      packages/nc-gui/components/smartsheet/grid/Table.vue
  7. 3
      packages/nc-gui/lib/types.ts
  8. 8
      packages/nc-gui/utils/cell.ts
  9. 26
      packages/nc-gui/utils/commonUtils.ts

2
packages/nc-gui/components/cell/MultiSelect.vue

@ -428,7 +428,7 @@ const onFocus = () => {
:style="{ :style="{
'display': '-webkit-box', 'display': '-webkit-box',
'max-width': '100%', 'max-width': '100%',
'-webkit-line-clamp': rowHeightTruncateLines(rowHeight), '-webkit-line-clamp': rowHeightTruncateLines(rowHeight, true),
'-webkit-box-orient': 'vertical', '-webkit-box-orient': 'vertical',
'overflow': 'hidden', 'overflow': 'hidden',
}" }"

2
packages/nc-gui/components/cell/Rating.vue

@ -72,7 +72,7 @@ watch(rateDomRef, () => {
'padding': isExpandedFormOpen ? '0px 8px' : '0px 2px', 'padding': isExpandedFormOpen ? '0px 8px' : '0px 2px',
'display': '-webkit-box', 'display': '-webkit-box',
'max-width': '100%', 'max-width': '100%',
'-webkit-line-clamp': rowHeightTruncateLines(rowHeight), '-webkit-line-clamp': rowHeight === 6 ? 5 : rowHeightTruncateLines(rowHeight, true),
'-webkit-box-orient': 'vertical', '-webkit-box-orient': 'vertical',
'overflow': 'hidden', 'overflow': 'hidden',
}" }"

22
packages/nc-gui/components/cell/TextArea.vue

@ -1,5 +1,4 @@
<script setup lang="ts"> <script setup lang="ts">
import type { VNodeRef } from '@vue/runtime-core'
import type { AIRecordType } from 'nocodb-sdk' import type { AIRecordType } from 'nocodb-sdk'
const props = defineProps<{ const props = defineProps<{
@ -70,9 +69,6 @@ const mousePosition = ref<
const isDragging = ref(false) const isDragging = ref(false)
const focus: VNodeRef = (el) =>
!isExpandedFormOpen.value && !isEditColumn.value && !isForm.value && (el as HTMLTextAreaElement)?.focus()
const height = computed(() => { const height = computed(() => {
if (isExpandedFormOpen.value) return 36 * 4 if (isExpandedFormOpen.value) return 36 * 4
@ -326,6 +322,14 @@ watch(
immediate: true, immediate: true,
}, },
) )
const textAreaRef = ref<HTMLTextAreaElement>()
watch(textAreaRef, (el) => {
if (el && !isExpandedFormOpen.value && !isEditColumn.value && !isForm.value) {
el.focus()
}
})
</script> </script>
<template> <template>
@ -394,7 +398,7 @@ watch(
}" }"
> >
<textarea <textarea
:ref="focus" ref="textAreaRef"
v-model="vModel" v-model="vModel"
:rows="isForm ? 5 : 4" :rows="isForm ? 5 : 4"
class="h-full w-full !outline-none nc-scrollbar-thin" class="h-full w-full !outline-none nc-scrollbar-thin"
@ -511,14 +515,10 @@ watch(
:class="{ :class="{
'right-1': isForm, 'right-1': isForm,
'right-0': !isForm, 'right-0': !isForm,
'top-0': isGrid && !isExpandedFormOpen && !isForm && !(!rowHeight || rowHeight === 1), 'top-0 right-1': isGrid && !isExpandedFormOpen && !isForm,
'!right-2 top-2': isGrid && !isExpandedFormOpen && !isForm && ((editEnabled && !isVisible) || isForm),
'top-1': !(isGrid && !isExpandedFormOpen && !isForm), 'top-1': !(isGrid && !isExpandedFormOpen && !isForm),
}" }"
:style="
isGrid && !isExpandedFormOpen && !isForm && (!rowHeight || rowHeight === 1)
? { top: '50%', transform: 'translateY(-50%)' }
: undefined
"
> >
<NcTooltip <NcTooltip
v-if="!isVisible && !isForm && !readOnly && props.isAi && !isExpandedFormOpen && !isEditColumn" v-if="!isVisible && !isForm && !readOnly && props.isAi && !isExpandedFormOpen && !isEditColumn"

2
packages/nc-gui/components/cell/User.vue

@ -403,7 +403,7 @@ const isCollaborator = (userIdOrEmail) => {
:style="{ :style="{
'display': '-webkit-box', 'display': '-webkit-box',
'max-width': '100%', 'max-width': '100%',
'-webkit-line-clamp': rowHeightTruncateLines(rowHeight), '-webkit-line-clamp': rowHeightTruncateLines(rowHeight, true),
'-webkit-box-orient': 'vertical', '-webkit-box-orient': 'vertical',
'overflow': 'hidden', 'overflow': 'hidden',
}" }"

20
packages/nc-gui/components/smartsheet/grid/InfiniteTable.vue

@ -195,6 +195,8 @@ const onXcResizing = (cn: string | undefined, event: any) => {
const size = event.detail.split('px')[0] const size = event.detail.split('px')[0]
gridViewCols.value[cn].width = `${normalizedWidth(metaColumnById.value[cn], size)}px` gridViewCols.value[cn].width = `${normalizedWidth(metaColumnById.value[cn], size)}px`
refreshFillHandle()
} }
const onXcStartResizing = (cn: string | undefined, event: any) => { const onXcStartResizing = (cn: string | undefined, event: any) => {
@ -1434,7 +1436,7 @@ const leftOffset = computed(() => {
const fillHandleTop = ref() const fillHandleTop = ref()
const fillHandleLeft = ref() const fillHandleLeft = ref()
const refreshFillHandle = () => { function refreshFillHandle() {
const rowIndex = isNaN(selectedRange.end.row) ? activeCell.row : selectedRange.end.row const rowIndex = isNaN(selectedRange.end.row) ? activeCell.row : selectedRange.end.row
const colIndex = isNaN(selectedRange.end.col) ? activeCell.col : selectedRange.end.col const colIndex = isNaN(selectedRange.end.col) ? activeCell.col : selectedRange.end.col
if (rowIndex !== null && colIndex !== null) { if (rowIndex !== null && colIndex !== null) {
@ -1896,7 +1898,7 @@ watch(vSelectedAllRecords, (selectedAll) => {
</template> </template>
</th> </th>
<th <th
v-if="fields[0] && fields[0].id" v-if="fields?.[0]?.id"
ref="primaryColHeader" ref="primaryColHeader"
v-xc-ver-resize v-xc-ver-resize
:data-col="fields[0].id" :data-col="fields[0].id"
@ -2724,10 +2726,18 @@ watch(vSelectedAllRecords, (selectedAll) => {
&.align-top { &.align-top {
@apply py-2; @apply py-2;
&:has(.nc-cell.nc-cell-longtext textarea) {
@apply py-0 pr-0;
}
} }
&.align-middle { &.align-middle {
@apply py-0; @apply py-0;
&:has(.nc-cell.nc-cell-longtext textarea) {
@apply pr-0;
}
} }
& > div { & > div {
@ -2753,7 +2763,7 @@ watch(vSelectedAllRecords, (selectedAll) => {
.nc-cell-field, .nc-cell-field,
input, input,
textarea { textarea {
@apply !text-small !p-0 m-0; @apply !text-small !pl-0 !py-0 m-0;
} }
&:not(.nc-display-value-cell) { &:not(.nc-display-value-cell) {
@ -2772,7 +2782,7 @@ watch(vSelectedAllRecords, (selectedAll) => {
a.nc-cell-field-link, a.nc-cell-field-link,
input, input,
textarea { textarea {
@apply !p-0 m-0; @apply !pl-0 !py-0 m-0;
} }
a.nc-cell-field-link { a.nc-cell-field-link {
@ -2786,7 +2796,7 @@ watch(vSelectedAllRecords, (selectedAll) => {
@apply leading-[18px]; @apply leading-[18px];
textarea { textarea {
@apply pr-2; @apply pr-8 !py-2;
} }
} }

20
packages/nc-gui/components/smartsheet/grid/Table.vue

@ -1214,6 +1214,8 @@ const onXcResizing = (cn: string | undefined, event: any) => {
const size = event.detail.split('px')[0] const size = event.detail.split('px')[0]
gridViewCols.value[cn].width = `${normalizedWidth(metaColumnById.value[cn], size)}px` gridViewCols.value[cn].width = `${normalizedWidth(metaColumnById.value[cn], size)}px`
refreshFillHandle()
} }
const onXcStartResizing = (cn: string | undefined, event: any) => { const onXcStartResizing = (cn: string | undefined, event: any) => {
@ -1376,7 +1378,7 @@ const topOffset = computed(() => {
const fillHandleTop = ref() const fillHandleTop = ref()
const fillHandleLeft = ref() const fillHandleLeft = ref()
const refreshFillHandle = () => { function refreshFillHandle() {
nextTick(() => { nextTick(() => {
const rowIndex = isNaN(selectedRange.end.row) ? activeCell.row : selectedRange.end.row const rowIndex = isNaN(selectedRange.end.row) ? activeCell.row : selectedRange.end.row
const colIndex = isNaN(selectedRange.end.col) ? activeCell.col : selectedRange.end.col const colIndex = isNaN(selectedRange.end.col) ? activeCell.col : selectedRange.end.col
@ -1834,7 +1836,7 @@ onKeyStroke('ArrowDown', onDown)
</div> </div>
</th> </th>
<th <th
v-if="fields[0] && fields[0].id" v-if="fields?.[0]?.id"
v-xc-ver-resize v-xc-ver-resize
:data-col="fields[0].id" :data-col="fields[0].id"
:data-title="fields[0].title" :data-title="fields[0].title"
@ -2739,10 +2741,18 @@ onKeyStroke('ArrowDown', onDown)
&.align-top { &.align-top {
@apply py-2; @apply py-2;
&:has(.nc-cell.nc-cell-longtext textarea) {
@apply py-0 pr-0;
}
} }
&.align-middle { &.align-middle {
@apply py-0; @apply py-0;
&:has(.nc-cell.nc-cell-longtext textarea) {
@apply pr-0;
}
} }
& > div { & > div {
@ -2768,7 +2778,7 @@ onKeyStroke('ArrowDown', onDown)
.nc-cell-field, .nc-cell-field,
input, input,
textarea { textarea {
@apply !text-small !p-0 m-0; @apply !text-small !pl-0 !py-0 m-0;
} }
&:not(.nc-display-value-cell) { &:not(.nc-display-value-cell) {
@ -2787,7 +2797,7 @@ onKeyStroke('ArrowDown', onDown)
a.nc-cell-field-link, a.nc-cell-field-link,
input, input,
textarea { textarea {
@apply !p-0 m-0; @apply !pl-0 !py-0 m-0;
} }
a.nc-cell-field-link { a.nc-cell-field-link {
@ -2801,7 +2811,7 @@ onKeyStroke('ArrowDown', onDown)
@apply leading-[18px]; @apply leading-[18px];
textarea { textarea {
@apply pr-2; @apply pr-8 !py-2;
} }
} }

3
packages/nc-gui/lib/types.ts

@ -306,6 +306,8 @@ interface ProductFeedItem {
type SordDirectionType = 'asc' | 'desc' | undefined type SordDirectionType = 'asc' | 'desc' | undefined
type NestedArray<T> = T | NestedArray<T>[]
export type { export type {
User, User,
ProjectMetaInfo, ProjectMetaInfo,
@ -341,4 +343,5 @@ export type {
SordDirectionType, SordDirectionType,
ProductFeedItem, ProductFeedItem,
Attachment, Attachment,
NestedArray,
} }

8
packages/nc-gui/utils/cell.ts

@ -107,14 +107,14 @@ export const rowHeightInPx: Record<string, number> = {
6: 120, 6: 120,
} }
export const rowHeightTruncateLines = (rowHeight?: number) => { export const rowHeightTruncateLines = (rowHeight?: number, isSelectOption = false) => {
switch (rowHeight) { switch (rowHeight) {
case 2: case 2:
return 3 return 2
case 4: case 4:
return 4 return isSelectOption ? 3 : 4
case 6: case 6:
return 6 return isSelectOption ? 4 : 6
default: default:
return 1 return 1
} }

26
packages/nc-gui/utils/commonUtils.ts

@ -75,11 +75,12 @@ export const isUnicodeEmoji = (emoji: string) => {
/** /**
* Performs a case-insensitive search to check if the `query` exists within the `source`. * Performs a case-insensitive search to check if the `query` exists within the `source`.
* *
* - If `source` is an array, the function checks if any element (converted to a string) contains the `query`. * - Handles strings, numbers, and arrays (including nested arrays) of strings/numbers.
* - If `source` is a string or number, it checks if the `query` exists within `source` (case-insensitively). * - Treats `undefined` as an empty string.
* - If `source` or `query` is `undefined`, they are treated as empty strings.
* *
* @param source - The value to search within. Can be a string, number, or an array of strings/numbers. * @param source - The value to search within. Can be:
* - A string or number.
* - A single-level or nested array of strings/numbers.
* @param query - The value to search for. Treated as an empty string if `undefined`. * @param query - The value to search for. Treated as an empty string if `undefined`.
* @returns `true` if the `query` is found within the `source` (case-insensitively), otherwise `false`. * @returns `true` if the `query` is found within the `source` (case-insensitively), otherwise `false`.
* *
@ -87,27 +88,24 @@ export const isUnicodeEmoji = (emoji: string) => {
* ```typescript * ```typescript
* // Single string or number search * // Single string or number search
* searchCompare("Hello World", "world"); // true * searchCompare("Hello World", "world"); // true
* searchCompare("OpenAI ChatGPT", "gpt"); // true * searchCompare(12345, "234"); // true
* searchCompare("TypeScript", "JavaScript"); // false
* *
* // Array search * // Array search
* searchCompare(["apple", "banana", "cherry"], "Banana"); // true * searchCompare(["apple", "banana", "cherry"], "Banana"); // true
* searchCompare([123, 456, 789], "456"); // true * searchCompare([123, 456, 789], "456"); // true
* searchCompare([null, undefined, "test"], "TEST"); // true *
* // Nested array search
* searchCompare(["apple", ["banana", ["cherry"]]], "cherry"); // true
* searchCompare([123, [456, [789]]], "456"); // true
* *
* // Handling undefined * // Handling undefined
* searchCompare(undefined, "test"); // false * searchCompare(undefined, "test"); // false
* searchCompare("test", undefined); // true * searchCompare("test", undefined); // true
* ``` * ```
*/ */
export const searchCompare = (source?: string | number | (string | number | undefined)[], query?: string): boolean => { export const searchCompare = (source?: NestedArray<string | number | undefined>, query?: string): boolean => {
if (ncIsArray(source)) { if (ncIsArray(source)) {
return source.some((item) => { return source.some((item) => searchCompare(item, query))
return (item || '')
.toString()
.toLowerCase()
.includes((query || '').toLowerCase())
})
} }
return (source || '') return (source || '')

Loading…
Cancel
Save