Browse Source

Merge pull request #7466 from nocodb/nc-fix/shared-base-view-expanded-form

Nc: Expanded form and cell fields bug fixes
pull/7479/head
Raju Udava 11 months ago committed by GitHub
parent
commit
bd7730d388
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 13
      packages/nc-gui/assets/style.scss
  2. 3
      packages/nc-gui/components/cell/Checkbox.vue
  3. 12
      packages/nc-gui/components/cell/Currency.vue
  4. 8
      packages/nc-gui/components/cell/DatePicker.vue
  5. 7
      packages/nc-gui/components/cell/DateTimePicker.vue
  6. 13
      packages/nc-gui/components/cell/Decimal.vue
  7. 18
      packages/nc-gui/components/cell/Duration.vue
  8. 23
      packages/nc-gui/components/cell/Email.vue
  9. 6
      packages/nc-gui/components/cell/Float.vue
  10. 9
      packages/nc-gui/components/cell/GeoData.vue
  11. 13
      packages/nc-gui/components/cell/Integer.vue
  12. 10
      packages/nc-gui/components/cell/Json.vue
  13. 7
      packages/nc-gui/components/cell/MultiSelect.vue
  14. 18
      packages/nc-gui/components/cell/Percent.vue
  15. 26
      packages/nc-gui/components/cell/PhoneNumber.vue
  16. 6
      packages/nc-gui/components/cell/Rating.vue
  17. 6
      packages/nc-gui/components/cell/RichText.vue
  18. 7
      packages/nc-gui/components/cell/SingleSelect.vue
  19. 11
      packages/nc-gui/components/cell/Text.vue
  20. 8
      packages/nc-gui/components/cell/TimePicker.vue
  21. 30
      packages/nc-gui/components/cell/Url.vue
  22. 7
      packages/nc-gui/components/cell/User.vue
  23. 7
      packages/nc-gui/components/cell/YearPicker.vue
  24. 2
      packages/nc-gui/components/dashboard/TreeView/ViewsNode.vue
  25. 4
      packages/nc-gui/components/smartsheet/Cell.vue
  26. 8
      packages/nc-gui/components/smartsheet/column/EditOrAdd.vue
  27. 12
      packages/nc-gui/components/smartsheet/column/LinkOptions.vue
  28. 13
      packages/nc-gui/components/smartsheet/expanded-form/index.vue
  29. 2
      packages/nc-gui/components/smartsheet/header/CellIcon.ts
  30. 2
      packages/nc-gui/components/smartsheet/header/VirtualCellIcon.ts
  31. 8
      packages/nc-gui/components/smartsheet/toolbar/SortListMenu.vue
  32. 2
      packages/nc-gui/components/virtual-cell/BelongsTo.vue
  33. 24
      packages/nc-gui/components/virtual-cell/Formula.vue
  34. 24
      packages/nc-gui/components/virtual-cell/Links.vue
  35. 4
      packages/nc-gui/components/virtual-cell/Lookup.vue
  36. 2
      packages/nc-gui/components/virtual-cell/Rollup.vue
  37. 6
      packages/nc-gui/components/virtual-cell/barcode/Barcode.vue
  38. 10
      packages/nc-gui/components/virtual-cell/components/ListChildItems.vue
  39. 11
      packages/nc-gui/components/virtual-cell/components/ListItem.vue
  40. 2
      packages/nc-gui/composables/useColumnCreateStore.ts

13
packages/nc-gui/assets/style.scss

@ -714,7 +714,7 @@ input[type='number'] {
} }
.nc-sidebar-node-btn:not(.nc-sidebar-expand) { .nc-sidebar-node-btn:not(.nc-sidebar-expand) {
@apply !xs:(hidden) @apply !xs:(hidden);
} }
} }
@ -727,13 +727,18 @@ input[type='number'] {
@apply xs:(opacity-100 hover:bg-gray-50); @apply xs:(opacity-100 hover:bg-gray-50);
.nc-icon { .nc-icon {
@apply xs:(visible opacity-100 !text-gray-500) @apply xs:(visible opacity-100 !text-gray-500);
} }
} }
.ant-message-notice-content { .ant-message-notice-content {
@apply !rounded-md; @apply !rounded-md;
.ant-message-custom-content{ .ant-message-custom-content{
@apply flex items-center @apply flex items-center;
} }
} }
svg.nc-cell-icon, svg.nc-virtual-cell-icon {
@apply w-1em h-1em flex-none;
font-size: 1rem;
}

3
packages/nc-gui/components/cell/Checkbox.vue

@ -90,12 +90,13 @@ useSelectedCellKeyupListener(active, (e) => {
'w-full justify-center': !isForm && !isGallery && !isExpandedFormOpen, 'w-full justify-center': !isForm && !isGallery && !isExpandedFormOpen,
'nc-cell-hover-show': !vModel && !readOnly, 'nc-cell-hover-show': !vModel && !readOnly,
'opacity-0': readOnly && !vModel, 'opacity-0': readOnly && !vModel,
'pointer-events-none': readOnly,
}" }"
:style="{ :style="{
height: height:
isForm || isExpandedFormOpen || isGallery || isEditColumnMenu ? undefined : `max(${(rowHeight || 1) * 1.8}rem, 41px)`, isForm || isExpandedFormOpen || isGallery || isEditColumnMenu ? undefined : `max(${(rowHeight || 1) * 1.8}rem, 41px)`,
}" }"
tabindex="0" :tabindex="readOnly ? -1 : 0"
@click="onClick(false, $event)" @click="onClick(false, $event)"
@keydown.enter.stop="onClick(true, $event)" @keydown.enter.stop="onClick(true, $event)"
> >

12
packages/nc-gui/components/cell/Currency.vue

@ -6,6 +6,7 @@ import {
EditModeInj, EditModeInj,
IsExpandedFormOpenInj, IsExpandedFormOpenInj,
IsFormInj, IsFormInj,
ReadonlyInj,
computed, computed,
inject, inject,
parseProp, parseProp,
@ -28,6 +29,8 @@ const editEnabled = inject(EditModeInj)!
const isEditColumn = inject(EditColumnInj, ref(false)) const isEditColumn = inject(EditColumnInj, ref(false))
const readOnly = inject(ReadonlyInj, ref(false))
const _vModel = useVModel(props, 'modelValue', emit) const _vModel = useVModel(props, 'modelValue', emit)
const vModel = computed({ const vModel = computed({
@ -87,12 +90,11 @@ onMounted(() => {
<template> <template>
<input <input
v-if="editEnabled" v-if="!readOnly && editEnabled"
:ref="focus" :ref="focus"
v-model="vModel" v-model="vModel"
type="number" type="number"
class="w-full h-full text-sm border-none rounded-md py-1 outline-none focus:outline-none focus:ring-0" class="nc-cell-field w-full h-full text-sm border-none rounded-md py-1 outline-none focus:outline-none focus:ring-0"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
:placeholder="isEditColumn ? $t('labels.optional') : ''" :placeholder="isEditColumn ? $t('labels.optional') : ''"
@blur="submitCurrency" @blur="submitCurrency"
@keydown.down.stop @keydown.down.stop
@ -105,10 +107,10 @@ onMounted(() => {
@contextmenu.stop @contextmenu.stop
/> />
<span v-else-if="vModel === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span> <span v-else-if="vModel === null && showNull" class="nc-cell-field nc-null uppercase">{{ $t('general.null') }}</span>
<!-- only show the numeric value as previously string value was accepted --> <!-- only show the numeric value as previously string value was accepted -->
<span v-else-if="!isNaN(vModel)">{{ currency }}</span> <span v-else-if="!isNaN(vModel)" class="nc-cell-field">{{ currency }}</span>
<!-- possibly unexpected string / null with showNull == false --> <!-- possibly unexpected string / null with showNull == false -->
<span v-else /> <span v-else />

8
packages/nc-gui/components/cell/DatePicker.vue

@ -7,7 +7,6 @@ import {
ColumnInj, ColumnInj,
EditColumnInj, EditColumnInj,
EditModeInj, EditModeInj,
IsExpandedFormOpenInj,
ReadonlyInj, ReadonlyInj,
computed, computed,
inject, inject,
@ -42,8 +41,6 @@ const readOnly = inject(ReadonlyInj, ref(false))
const isEditColumn = inject(EditColumnInj, ref(false)) const isEditColumn = inject(EditColumnInj, ref(false))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))
const active = inject(ActiveCellInj, ref(false)) const active = inject(ActiveCellInj, ref(false))
const editable = inject(EditModeInj, ref(false)) const editable = inject(EditModeInj, ref(false))
@ -240,11 +237,12 @@ const clickHandler = () => {
<template> <template>
<a-date-picker <a-date-picker
v-model:value="localState" v-model:value="localState"
:disabled="readOnly"
:picker="picker" :picker="picker"
:tabindex="0" :tabindex="0"
:bordered="false" :bordered="false"
class="!w-full !py-1 !border-none !text-current" class="nc-cell-field !w-full !py-1 !border-none !text-current"
:class="{ 'nc-null': modelValue === null && showNull, '!px-2': isExpandedFormOpen, '!px-0': !isExpandedFormOpen }" :class="{ 'nc-null': modelValue === null && showNull }"
:format="dateFormat" :format="dateFormat"
:placeholder="placeholder" :placeholder="placeholder"
:allow-clear="!readOnly && !localState && !isPk" :allow-clear="!readOnly && !localState && !isPk"

7
packages/nc-gui/components/cell/DateTimePicker.vue

@ -6,7 +6,6 @@ import {
CellClickHookInj, CellClickHookInj,
ColumnInj, ColumnInj,
EditColumnInj, EditColumnInj,
IsExpandedFormOpenInj,
ReadonlyInj, ReadonlyInj,
inject, inject,
isDrawerOrModalExist, isDrawerOrModalExist,
@ -40,8 +39,6 @@ const { t } = useI18n()
const isEditColumn = inject(EditColumnInj, ref(false)) const isEditColumn = inject(EditColumnInj, ref(false))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))
const column = inject(ColumnInj)! const column = inject(ColumnInj)!
const isDateInvalid = ref(false) const isDateInvalid = ref(false)
@ -297,8 +294,8 @@ const isColDisabled = computed(() => {
:disabled="isColDisabled" :disabled="isColDisabled"
:show-time="true" :show-time="true"
:bordered="false" :bordered="false"
class="!w-full !py-1 !border-none !text-current" class="nc-cell-field !w-full !py-1 !border-none !text-current"
:class="{ 'nc-null': modelValue === null && showNull, '!px-2': isExpandedFormOpen, '!px-0': !isExpandedFormOpen }" :class="{ 'nc-null': modelValue === null && showNull }"
:format="dateTimeFormat" :format="dateTimeFormat"
:placeholder="placeholder" :placeholder="placeholder"
:allow-clear="!readOnly && !localState && !isPk" :allow-clear="!readOnly && !localState && !isPk"

13
packages/nc-gui/components/cell/Decimal.vue

@ -1,6 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { VNodeRef } from '@vue/runtime-core' import type { VNodeRef } from '@vue/runtime-core'
import { EditColumnInj, EditModeInj, IsExpandedFormOpenInj, IsFormInj, inject, useVModel } from '#imports' import { EditColumnInj, EditModeInj, IsExpandedFormOpenInj, IsFormInj, ReadonlyInj, inject, useVModel } from '#imports'
interface Props { interface Props {
// when we set a number, then it is number type // when we set a number, then it is number type
@ -25,6 +25,8 @@ const column = inject(ColumnInj, null)!
const isEditColumn = inject(EditColumnInj, ref(false)) const isEditColumn = inject(EditColumnInj, ref(false))
const readOnly = inject(ReadonlyInj, ref(false))
const domRef = ref<HTMLElement>() const domRef = ref<HTMLElement>()
const meta = computed(() => { const meta = computed(() => {
@ -94,11 +96,10 @@ watch(isExpandedFormOpen, () => {
<template> <template>
<input <input
v-if="editEnabled" v-if="!readOnly && editEnabled"
:ref="focus" :ref="focus"
v-model="vModel" v-model="vModel"
class="outline-none py-1 border-none rounded-md w-full h-full !text-sm" class="nc-cell-field outline-none py-1 border-none rounded-md w-full h-full !text-sm"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
type="number" type="number"
:step="precision" :step="precision"
:placeholder="isEditColumn ? $t('labels.optional') : ''" :placeholder="isEditColumn ? $t('labels.optional') : ''"
@ -112,8 +113,8 @@ watch(isExpandedFormOpen, () => {
@selectstart.capture.stop @selectstart.capture.stop
@mousedown.stop @mousedown.stop
/> />
<span v-else-if="vModel === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span> <span v-else-if="vModel === null && showNull" class="nc-cell-field nc-null uppercase">{{ $t('general.null') }}</span>
<span v-else class="text-sm">{{ displayValue }}</span> <span v-else class="nc-cell-field text-sm">{{ displayValue }}</span>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">

18
packages/nc-gui/components/cell/Duration.vue

@ -6,6 +6,7 @@ import {
EditModeInj, EditModeInj,
IsExpandedFormOpenInj, IsExpandedFormOpenInj,
IsFormInj, IsFormInj,
ReadonlyInj,
computed, computed,
convertDurationToSeconds, convertDurationToSeconds,
convertMS2Duration, convertMS2Duration,
@ -32,14 +33,16 @@ const column = inject(ColumnInj)
const editEnabled = inject(EditModeInj) const editEnabled = inject(EditModeInj)
const isEditColumn = inject(EditColumnInj, ref(false))
const readOnly = inject(ReadonlyInj, ref(false))
const showWarningMessage = ref(false) const showWarningMessage = ref(false)
const durationInMS = ref(0) const durationInMS = ref(0)
const isEdited = ref(false) const isEdited = ref(false)
const isEditColumn = inject(EditColumnInj, ref(false))
const durationType = computed(() => parseProp(column?.value?.meta)?.duration || 0) const durationType = computed(() => parseProp(column?.value?.meta)?.duration || 0)
const durationPlaceholder = computed(() => const durationPlaceholder = computed(() =>
@ -93,11 +96,10 @@ const focus: VNodeRef = (el) =>
<template> <template>
<div class="duration-cell-wrapper"> <div class="duration-cell-wrapper">
<input <input
v-if="editEnabled" v-if="!readOnly && editEnabled"
:ref="focus" :ref="focus"
v-model="localState" v-model="localState"
class="w-full !border-none !outline-none py-1" class="nc-cell-field w-full !border-none !outline-none py-1"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
:placeholder="durationPlaceholder" :placeholder="durationPlaceholder"
@blur="submitDuration" @blur="submitDuration"
@keypress="checkDurationFormat($event)" @keypress="checkDurationFormat($event)"
@ -111,11 +113,11 @@ const focus: VNodeRef = (el) =>
@mousedown.stop @mousedown.stop
/> />
<span v-else-if="modelValue === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span> <span v-else-if="modelValue === null && showNull" class="nc-cell-field nc-null uppercase">{{ $t('general.null') }}</span>
<span v-else> {{ localState }}</span> <span v-else class="nc-cell-field"> {{ localState }}</span>
<div v-if="showWarningMessage && showValidationError" class="duration-warning"> <div v-if="showWarningMessage && showValidationError" class="nc-cell-field duration-warning">
{{ $t('msg.plsEnterANumber') }} {{ $t('msg.plsEnterANumber') }}
</div> </div>
</div> </div>

23
packages/nc-gui/components/cell/Email.vue

@ -6,6 +6,7 @@ import {
IsExpandedFormOpenInj, IsExpandedFormOpenInj,
IsFormInj, IsFormInj,
IsSurveyFormInj, IsSurveyFormInj,
ReadonlyInj,
computed, computed,
inject, inject,
useI18n, useI18n,
@ -30,13 +31,15 @@ const editEnabled = inject(EditModeInj)!
const column = inject(ColumnInj)! const column = inject(ColumnInj)!
// Used in the logic of when to display error since we are not storing the email if it's not valid
const localState = ref(value)
const isSurveyForm = inject(IsSurveyFormInj, ref(false)) const isSurveyForm = inject(IsSurveyFormInj, ref(false))
const isEditColumn = inject(EditColumnInj, ref(false)) const isEditColumn = inject(EditColumnInj, ref(false))
const readOnly = inject(ReadonlyInj, ref(false))
// Used in the logic of when to display error since we are not storing the email if it's not valid
const localState = ref(value)
const vModel = computed({ const vModel = computed({
get: () => value, get: () => value,
set: (val) => { set: (val) => {
@ -71,11 +74,10 @@ watch(
<template> <template>
<input <input
v-if="editEnabled" v-if="!readOnly && editEnabled"
:ref="focus" :ref="focus"
v-model="vModel" v-model="vModel"
class="w-full outline-none text-sm py-1" class="nc-cell-field w-full outline-none text-sm py-1"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
:placeholder="isEditColumn ? $t('labels.optional') : ''" :placeholder="isEditColumn ? $t('labels.optional') : ''"
@blur="editEnabled = false" @blur="editEnabled = false"
@keydown.down.stop @keydown.down.stop
@ -87,17 +89,18 @@ watch(
@mousedown.stop @mousedown.stop
/> />
<span v-else-if="vModel === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span> <span v-else-if="vModel === null && showNull" class="nc-cell-field nc-null uppercase">{{ $t('general.null') }}</span>
<nuxt-link <nuxt-link
v-else-if="validEmail" v-else-if="validEmail"
no-ref no-ref
class="text-sm underline hover:opacity-75 inline-block" class="py-1 text-sm underline hover:opacity-75 inline-block"
:href="`mailto:${vModel}`" :href="`mailto:${vModel}`"
target="_blank" target="_blank"
:tabindex="readOnly ? -1 : 0"
> >
<LazyCellClampedText :value="vModel" :lines="rowHeight" /> <LazyCellClampedText :value="vModel" :lines="rowHeight" class="nc-cell-field" />
</nuxt-link> </nuxt-link>
<LazyCellClampedText v-else :value="vModel" :lines="rowHeight" /> <LazyCellClampedText v-else :value="vModel" :lines="rowHeight" class="nc-cell-field" />
</template> </template>

6
packages/nc-gui/components/cell/Float.vue

@ -51,7 +51,7 @@ const focus: VNodeRef = (el) =>
v-if="editEnabled" v-if="editEnabled"
:ref="focus" :ref="focus"
v-model="vModel" v-model="vModel"
class="outline-none px-1 border-none w-full h-full text-sm" class="nc-cell-field outline-none px-1 border-none w-full h-full text-sm"
type="number" type="number"
step="0.1" step="0.1"
:placeholder="isEditColumn ? $t('labels.optional') : ''" :placeholder="isEditColumn ? $t('labels.optional') : ''"
@ -64,8 +64,8 @@ const focus: VNodeRef = (el) =>
@selectstart.capture.stop @selectstart.capture.stop
@mousedown.stop @mousedown.stop
/> />
<span v-else-if="vModel === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span> <span v-else-if="vModel === null && showNull" class="nc-cell-field nc-null uppercase">{{ $t('general.null') }}</span>
<span v-else class="text-sm">{{ vModel }}</span> <span v-else class="nc-cell-field text-sm">{{ vModel }}</span>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">

9
packages/nc-gui/components/cell/GeoData.vue

@ -1,6 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { GeoLocationType } from 'nocodb-sdk' import type { GeoLocationType } from 'nocodb-sdk'
import { Modal as AModal, IsExpandedFormOpenInj, iconMap, latLongToJoinedString, useVModel } from '#imports' import { Modal as AModal, iconMap, latLongToJoinedString, useVModel } from '#imports'
interface Props { interface Props {
modelValue?: string | null modelValue?: string | null
@ -16,8 +16,6 @@ const emits = defineEmits<Emits>()
const vModel = useVModel(props, 'modelValue', emits) const vModel = useVModel(props, 'modelValue', emits)
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))
const isExpanded = ref(false) const isExpanded = ref(false)
const isLoading = ref(false) const isLoading = ref(false)
@ -105,10 +103,7 @@ const openInOSM = () => {
v-else v-else
data-testid="nc-geo-data-lat-long-set" data-testid="nc-geo-data-lat-long-set"
tabindex="0" tabindex="0"
class="h-full w-full flex items-center py-1 focus-visible:!outline-none focus:!outline-none" class="nc-cell-field h-full w-full flex items-center py-1 focus-visible:!outline-none focus:!outline-none"
:class="{
'px-2': isExpandedFormOpen,
}"
> >
{{ latLongStr }} {{ latLongStr }}
</div> </div>

13
packages/nc-gui/components/cell/Integer.vue

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { VNodeRef } from '@vue/runtime-core' import type { VNodeRef } from '@vue/runtime-core'
import { EditColumnInj, EditModeInj, IsExpandedFormOpenInj, IsFormInj, inject, useVModel } from '#imports' import { EditColumnInj, EditModeInj, IsExpandedFormOpenInj, IsFormInj, ReadonlyInj, inject, useVModel } from '#imports'
interface Props { interface Props {
// when we set a number, then it is number type // when we set a number, then it is number type
@ -23,6 +23,8 @@ const editEnabled = inject(EditModeInj)
const isEditColumn = inject(EditColumnInj, ref(false)) const isEditColumn = inject(EditColumnInj, ref(false))
const readOnly = inject(ReadonlyInj, ref(false))
const _vModel = useVModel(props, 'modelValue', emits) const _vModel = useVModel(props, 'modelValue', emits)
const displayValue = computed(() => { const displayValue = computed(() => {
@ -85,11 +87,10 @@ function onKeyDown(e: any) {
<template> <template>
<input <input
v-if="editEnabled" v-if="!readOnly && editEnabled"
:ref="focus" :ref="focus"
v-model="vModel" v-model="vModel"
class="outline-none py-1 border-none w-full h-full text-sm" class="nc-cell-field outline-none py-1 border-none w-full h-full text-sm"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
type="number" type="number"
style="letter-spacing: 0.06rem" style="letter-spacing: 0.06rem"
:placeholder="isEditColumn ? $t('labels.optional') : ''" :placeholder="isEditColumn ? $t('labels.optional') : ''"
@ -103,8 +104,8 @@ function onKeyDown(e: any) {
@selectstart.capture.stop @selectstart.capture.stop
@mousedown.stop @mousedown.stop
/> />
<span v-else-if="vModel === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span> <span v-else-if="vModel === null && showNull" class="nc-cell-field nc-null uppercase">{{ $t('general.null') }}</span>
<span v-else class="text-sm">{{ displayValue }}</span> <span v-else class="nc-cell-field text-sm">{{ displayValue }}</span>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">

10
packages/nc-gui/components/cell/Json.vue

@ -35,7 +35,7 @@ const active = inject(ActiveCellInj, ref(false))
const isForm = inject(IsFormInj, ref(false)) const isForm = inject(IsFormInj, ref(false))
const readonly = inject(ReadonlyInj) const readOnly = inject(ReadonlyInj, ref(false))
const vModel = useVModel(props, 'modelValue', emits) const vModel = useVModel(props, 'modelValue', emits)
@ -158,7 +158,7 @@ watch(isExpanded, () => {
:footer="null" :footer="null"
:wrap-class-name="isExpanded ? '!z-1051' : null" :wrap-class-name="isExpanded ? '!z-1051' : null"
> >
<div v-if="editEnabled && !readonly" class="flex flex-col w-full" @mousedown.stop @mouseup.stop @click.stop> <div v-if="editEnabled && !readOnly" class="flex flex-col w-full" @mousedown.stop @mouseup.stop @click.stop>
<div class="flex flex-row justify-between pt-1 pb-2 nc-json-action" @mousedown.stop> <div class="flex flex-row justify-between pt-1 pb-2 nc-json-action" @mousedown.stop>
<a-button type="text" size="small" @click="isExpanded = !isExpanded"> <a-button type="text" size="small" @click="isExpanded = !isExpanded">
<CilFullscreenExit v-if="isExpanded" class="h-2.5" /> <CilFullscreenExit v-if="isExpanded" class="h-2.5" />
@ -187,14 +187,14 @@ watch(isExpanded, () => {
@update:model-value="localValue = $event" @update:model-value="localValue = $event"
/> />
<span v-if="error" class="text-xs w-full py-1 text-red-500"> <span v-if="error" class="nc-cell-field text-xs w-full py-1 text-red-500">
{{ error.toString() }} {{ error.toString() }}
</span> </span>
</div> </div>
<span v-else-if="vModel === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span> <span v-else-if="vModel === null && showNull" class="nc-cell-field nc-null uppercase">{{ $t('general.null') }}</span>
<LazyCellClampedText v-else :value="vModel" :lines="rowHeight" /> <LazyCellClampedText v-else :value="vModel" :lines="rowHeight" class="nc-cell-field" />
</component> </component>
</template> </template>

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

@ -8,7 +8,6 @@ import {
ColumnInj, ColumnInj,
EditColumnInj, EditColumnInj,
EditModeInj, EditModeInj,
IsExpandedFormOpenInj,
IsKanbanInj, IsKanbanInj,
ReadonlyInj, ReadonlyInj,
RowHeightInj, RowHeightInj,
@ -64,8 +63,6 @@ const isEditColumn = inject(EditColumnInj, ref(false))
const rowHeight = inject(RowHeightInj, ref(undefined)) const rowHeight = inject(RowHeightInj, ref(undefined))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const selectedIds = ref<string[]>([]) const selectedIds = ref<string[]>([])
const aselect = ref<typeof AntSelect>() const aselect = ref<typeof AntSelect>()
@ -355,8 +352,8 @@ const onFocus = () => {
<template> <template>
<div <div
class="nc-multi-select h-full w-full flex items-center" class="nc-cell-field nc-multi-select h-full w-full flex items-center"
:class="{ 'read-only': readOnly, 'px-2': isExpandedFormOpen }" :class="{ 'read-only': readOnly }"
@click="toggleMenu" @click="toggleMenu"
> >
<div <div

18
packages/nc-gui/components/cell/Percent.vue

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { VNodeRef } from '@vue/runtime-core' import type { VNodeRef } from '@vue/runtime-core'
import { EditColumnInj, EditModeInj, IsExpandedFormOpenInj, IsFormInj, inject, useVModel } from '#imports' import { EditColumnInj, EditModeInj, IsExpandedFormOpenInj, IsFormInj, ReadonlyInj, inject, useVModel } from '#imports'
interface Props { interface Props {
modelValue?: number | string | null modelValue?: number | string | null
@ -14,10 +14,12 @@ const { showNull } = useGlobal()
const column = inject(ColumnInj)! const column = inject(ColumnInj)!
const editEnabled = inject(EditModeInj) const editEnabled = inject(EditModeInj, ref(false))
const isEditColumn = inject(EditColumnInj, ref(false)) const isEditColumn = inject(EditColumnInj, ref(false))
const readOnly = inject(ReadonlyInj, ref(false))
const _vModel = useVModel(props, 'modelValue', emits) const _vModel = useVModel(props, 'modelValue', emits)
const wrapperRef = ref<HTMLElement>() const wrapperRef = ref<HTMLElement>()
@ -118,18 +120,18 @@ const onTabPress = (e: KeyboardEvent) => {
<template> <template>
<div <div
ref="wrapperRef" ref="wrapperRef"
tabindex="0" :tabindex="readOnly ? -1 : 0"
class="nc-filter-value-select w-full focus:outline-transparent" class="nc-filter-value-select w-full focus:outline-transparent"
:class="readOnly ? 'cursor-not-allowed pointer-events-none' : ''"
@mouseover="onMouseover" @mouseover="onMouseover"
@mouseleave="onMouseleave" @mouseleave="onMouseleave"
@focus="onWrapperFocus" @focus="onWrapperFocus"
> >
<input <input
v-if="editEnabled" v-if="!readOnly && editEnabled && (isExpandedFormOpen ? expandedEditEnabled : true)"
:ref="focus" :ref="focus"
v-model="vModel" v-model="vModel"
class="w-full !text-sm !border-none !outline-none focus:ring-0 text-base py-1" class="nc-cell-field w-full !text-sm !border-none !outline-none focus:ring-0 text-base py-1"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
type="number" type="number"
:placeholder="isEditColumn ? $t('labels.optional') : ''" :placeholder="isEditColumn ? $t('labels.optional') : ''"
@blur="onBlur" @blur="onBlur"
@ -143,7 +145,7 @@ const onTabPress = (e: KeyboardEvent) => {
@selectstart.capture.stop @selectstart.capture.stop
@mousedown.stop @mousedown.stop
/> />
<span v-else-if="vModel === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span> <span v-else-if="vModel === null && showNull" class="nc-cell-field nc-null uppercase">{{ $t('general.null') }}</span>
<div v-else-if="percentMeta.is_progress === true && vModel !== null && vModel !== undefined" class="px-2"> <div v-else-if="percentMeta.is_progress === true && vModel !== null && vModel !== undefined" class="px-2">
<a-progress <a-progress
:percent="Number(parseFloat(vModel.toString()).toFixed(2))" :percent="Number(parseFloat(vModel.toString()).toFixed(2))"
@ -155,7 +157,7 @@ const onTabPress = (e: KeyboardEvent) => {
/> />
</div> </div>
<!-- nbsp to keep height even if vModel is zero length --> <!-- nbsp to keep height even if vModel is zero length -->
<span v-else>{{ vModel }}&nbsp;</span> <span v-else class="nc-cell-field">{{ vModel }}&nbsp;</span>
</div> </div>
</template> </template>

26
packages/nc-gui/components/cell/PhoneNumber.vue

@ -17,17 +17,19 @@ const { showNull } = useGlobal()
const { t } = useI18n() const { t } = useI18n()
const editEnabled = inject(EditModeInj)! const editEnabled = inject(EditModeInj, ref(false))
const isEditColumn = inject(EditColumnInj, ref(false)) const isEditColumn = inject(EditColumnInj, ref(false))
const column = inject(ColumnInj)! const column = inject(ColumnInj)!
const isSurveyForm = inject(IsSurveyFormInj, ref(false))
const readOnly = inject(ReadonlyInj, ref(false))
// Used in the logic of when to display error since we are not storing the phone if it's not valid // Used in the logic of when to display error since we are not storing the phone if it's not valid
const localState = ref(value) const localState = ref(value)
const isSurveyForm = inject(IsSurveyFormInj, ref(false))
const vModel = computed({ const vModel = computed({
get: () => value, get: () => value,
set: (val) => { set: (val) => {
@ -38,7 +40,7 @@ const vModel = computed({
}, },
}) })
const validEmail = computed(() => vModel.value && isMobilePhone(vModel.value)) const validPhoneNumber = computed(() => vModel.value && isMobilePhone(vModel.value))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))! const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
@ -62,11 +64,10 @@ watch(
<template> <template>
<input <input
v-if="editEnabled" v-if="!readOnly && editEnabled"
:ref="focus" :ref="focus"
v-model="vModel" v-model="vModel"
class="w-full outline-none text-sm py-1" class="nc-cell-field w-full outline-none text-sm py-1"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
:placeholder="isEditColumn ? $t('labels.optional') : ''" :placeholder="isEditColumn ? $t('labels.optional') : ''"
@blur="editEnabled = false" @blur="editEnabled = false"
@keydown.down.stop @keydown.down.stop
@ -78,17 +79,18 @@ watch(
@mousedown.stop @mousedown.stop
/> />
<span v-else-if="vModel === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span> <span v-else-if="vModel === null && showNull" class="nc-cell-field nc-null uppercase">{{ $t('general.null') }}</span>
<a <a
v-else-if="validEmail" v-else-if="validPhoneNumber"
class="text-sm underline hover:opacity-75" class="py-1 text-sm underline hover:opacity-75 inline-block"
:href="`tel:${vModel}`" :href="`tel:${vModel}`"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
:tabindex="readOnly ? -1 : 0"
> >
<LazyCellClampedText :value="vModel" :lines="rowHeight" /> <LazyCellClampedText :value="vModel" :lines="rowHeight" class="nc-cell-field" />
</a> </a>
<LazyCellClampedText v-else :value="vModel" :lines="rowHeight" /> <LazyCellClampedText v-else :value="vModel" :lines="rowHeight" class="nc-cell-field" />
</template> </template>

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

@ -3,6 +3,7 @@ import {
ActiveCellInj, ActiveCellInj,
ColumnInj, ColumnInj,
IsExpandedFormOpenInj, IsExpandedFormOpenInj,
ReadonlyInj,
computed, computed,
inject, inject,
parseProp, parseProp,
@ -19,7 +20,7 @@ const emits = defineEmits(['update:modelValue'])
const column = inject(ColumnInj)! const column = inject(ColumnInj)!
const readonly = inject(ReadonlyInj, ref(false)) const readOnly = inject(ReadonlyInj, ref(false))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))! const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
@ -73,8 +74,9 @@ watch(rateDomRef, () => {
<a-rate <a-rate
ref="rateDomRef" ref="rateDomRef"
v-model:value="vModel" v-model:value="vModel"
:disabled="readonly" :disabled="readOnly"
:count="ratingMeta.max" :count="ratingMeta.max"
:class="readOnly ? 'pointer-events-none' : ''"
:style="`color: ${ratingMeta.color}; padding: ${isExpandedFormOpen ? '0px 8px' : '0px 5px'};`" :style="`color: ${ratingMeta.color}; padding: ${isExpandedFormOpen ? '0px 8px' : '0px 5px'};`"
@keydown="onKeyPress" @keydown="onKeyPress"
> >

6
packages/nc-gui/components/cell/RichText.vue

@ -8,7 +8,7 @@ import { generateJSON } from '@tiptap/html'
import Underline from '@tiptap/extension-underline' import Underline from '@tiptap/extension-underline'
import { TaskItem } from '@/helpers/dbTiptapExtensions/task-item' import { TaskItem } from '@/helpers/dbTiptapExtensions/task-item'
import { Link } from '@/helpers/dbTiptapExtensions/links' import { Link } from '@/helpers/dbTiptapExtensions/links'
import { IsExpandedFormOpenInj, RowHeightInj } from '#imports' import { IsExpandedFormOpenInj, ReadonlyInj, RowHeightInj } from '#imports'
const props = defineProps<{ const props = defineProps<{
value?: string | null value?: string | null
@ -24,6 +24,8 @@ const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const rowHeight = inject(RowHeightInj, ref(1 as const)) const rowHeight = inject(RowHeightInj, ref(1 as const))
const readOnlyCell = inject(ReadonlyInj, ref(false))
const turndownService = new TurndownService({}) const turndownService = new TurndownService({})
turndownService.addRule('lineBreak', { turndownService.addRule('lineBreak', {
@ -174,7 +176,7 @@ watch(editorDom, () => {
'nc-rich-text-embed flex flex-col pl-1 w-full': !fullMode, 'nc-rich-text-embed flex flex-col pl-1 w-full': !fullMode,
'readonly': readOnly, 'readonly': readOnly,
}" }"
tabindex="0" :tabindex="readOnlyCell ? -1 : 0"
> >
<div <div
v-if="showMenu && !readOnly" v-if="showMenu && !readOnly"

7
packages/nc-gui/components/cell/SingleSelect.vue

@ -8,7 +8,6 @@ import {
ColumnInj, ColumnInj,
EditColumnInj, EditColumnInj,
EditModeInj, EditModeInj,
IsExpandedFormOpenInj,
IsFormInj, IsFormInj,
IsKanbanInj, IsKanbanInj,
ReadonlyInj, ReadonlyInj,
@ -48,8 +47,6 @@ const activeCell = inject(ActiveCellInj, ref(false))
const isForm = inject(IsFormInj, ref(false)) const isForm = inject(IsFormInj, ref(false))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
// use both ActiveCellInj or EditModeInj to determine the active state // use both ActiveCellInj or EditModeInj to determine the active state
// since active will be false in case of form view // since active will be false in case of form view
const active = computed(() => activeCell.value || isEditable.value || isForm.value) const active = computed(() => activeCell.value || isEditable.value || isForm.value)
@ -274,8 +271,8 @@ const onFocus = () => {
<template> <template>
<div <div
class="h-full w-full flex items-center nc-single-select focus:outline-transparent" class="nc-cell-field h-full w-full flex items-center nc-single-select focus:outline-transparent"
:class="{ 'read-only': readOnly, 'px-2': isExpandedFormOpen }" :class="{ 'read-only': readOnly }"
@click="toggleMenu" @click="toggleMenu"
@keydown.enter.stop.prevent="toggleMenu" @keydown.enter.stop.prevent="toggleMenu"
> >

11
packages/nc-gui/components/cell/Text.vue

@ -28,7 +28,7 @@ const isEditColumn = inject(EditColumnInj, ref(false))
const rowHeight = inject(RowHeightInj, ref(undefined)) const rowHeight = inject(RowHeightInj, ref(undefined))
const readonly = inject(ReadonlyInj, ref(false)) const readOnly = inject(ReadonlyInj, ref(false))
const vModel = useVModel(props, 'modelValue', emits) const vModel = useVModel(props, 'modelValue', emits)
@ -42,11 +42,10 @@ const focus: VNodeRef = (el) =>
<template> <template>
<input <input
v-if="!readonly && editEnabled" v-if="!readOnly && editEnabled"
:ref="focus" :ref="focus"
v-model="vModel" v-model="vModel"
class="h-full w-full outline-none py-1 bg-transparent" class="nc-cell-field h-full w-full outline-none py-1 bg-transparent"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
:placeholder="isEditColumn ? $t('labels.optional') : ''" :placeholder="isEditColumn ? $t('labels.optional') : ''"
@blur="editEnabled = false" @blur="editEnabled = false"
@keydown.down.stop @keydown.down.stop
@ -58,7 +57,7 @@ const focus: VNodeRef = (el) =>
@mousedown.stop @mousedown.stop
/> />
<span v-else-if="vModel === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span> <span v-else-if="vModel === null && showNull" class="nc-cell-field nc-null uppercase">{{ $t('general.null') }}</span>
<LazyCellClampedText v-else :value="vModel" :lines="rowHeight" :style="{ 'word-break': 'break-word' }" /> <LazyCellClampedText v-else class="nc-cell-field" :value="vModel" :lines="rowHeight" :style="{ 'word-break': 'break-word' }" />
</template> </template>

8
packages/nc-gui/components/cell/TimePicker.vue

@ -3,7 +3,6 @@ import dayjs from 'dayjs'
import { import {
ActiveCellInj, ActiveCellInj,
EditColumnInj, EditColumnInj,
IsExpandedFormOpenInj,
ReadonlyInj, ReadonlyInj,
inject, inject,
onClickOutside, onClickOutside,
@ -35,8 +34,6 @@ const isEditColumn = inject(EditColumnInj, ref(false))
const column = inject(ColumnInj)! const column = inject(ColumnInj)!
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const isTimeInvalid = ref(false) const isTimeInvalid = ref(false)
const dateFormat = isMysql(column.value.source_id) ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD HH:mm:ssZ' const dateFormat = isMysql(column.value.source_id) ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD HH:mm:ssZ'
@ -129,12 +126,13 @@ useSelectedCellKeyupListener(active, (e: KeyboardEvent) => {
<template> <template>
<a-time-picker <a-time-picker
v-model:value="localState" v-model:value="localState"
:disabled="readOnly"
:show-time="true" :show-time="true"
:bordered="false" :bordered="false"
use12-hours use12-hours
format="HH:mm" format="HH:mm"
class="!w-full !py-1 !border-none !text-current" class="nc-cell-field !w-full !py-1 !border-none !text-current"
:class="{ 'nc-null': modelValue === null && showNull, '!px-2': isExpandedFormOpen, '!px-0': !isExpandedFormOpen }" :class="{ 'nc-null': modelValue === null && showNull }"
:placeholder="placeholder" :placeholder="placeholder"
:allow-clear="!readOnly && !localState && !isPk" :allow-clear="!readOnly && !localState && !isPk"
:input-read-only="true" :input-read-only="true"

30
packages/nc-gui/components/cell/Url.vue

@ -8,6 +8,7 @@ import {
IsExpandedFormOpenInj, IsExpandedFormOpenInj,
IsFormInj, IsFormInj,
IsSurveyFormInj, IsSurveyFormInj,
ReadonlyInj,
computed, computed,
inject, inject,
isValidURL, isValidURL,
@ -39,13 +40,15 @@ const isEditColumn = inject(EditColumnInj, ref(false))
const disableOverlay = inject(CellUrlDisableOverlayInj, ref(false)) const disableOverlay = inject(CellUrlDisableOverlayInj, ref(false))
// Used in the logic of when to display error since we are not storing the url if it's not valid
const localState = ref(value)
const rowHeight = inject(RowHeightInj, ref(undefined)) const rowHeight = inject(RowHeightInj, ref(undefined))
const isSurveyForm = inject(IsSurveyFormInj, ref(false)) const isSurveyForm = inject(IsSurveyFormInj, ref(false))
const readOnly = inject(ReadonlyInj, ref(false))
// Used in the logic of when to display error since we are not storing the url if it's not valid
const localState = ref(value)
const vModel = computed({ const vModel = computed({
get: () => value, get: () => value,
set: (val) => { set: (val) => {
@ -92,12 +95,11 @@ watch(
<template> <template>
<div class="flex flex-row items-center justify-between w-full h-full"> <div class="flex flex-row items-center justify-between w-full h-full">
<input <input
v-if="editEnabled" v-if="!readOnly && editEnabled"
:ref="focus" :ref="focus"
v-model="vModel" v-model="vModel"
:placeholder="isEditColumn ? $t('labels.enterDefaultUrlOptional') : ''" :placeholder="isEditColumn ? $t('labels.enterDefaultUrlOptional') : ''"
class="outline-none text-sm w-full py-1 bg-transparent h-full" class="nc-cell-field outline-none text-sm w-full py-1 bg-transparent h-full"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
@blur="editEnabled = false" @blur="editEnabled = false"
@keydown.down.stop @keydown.down.stop
@keydown.left.stop @keydown.left.stop
@ -108,31 +110,35 @@ watch(
@mousedown.stop @mousedown.stop
/> />
<span v-else-if="vModel === null && showNull" class="nc-null uppercase"> {{ $t('general.null') }}</span> <span v-else-if="vModel === null && showNull" class="nc-cell-field nc-null uppercase"> {{ $t('general.null') }}</span>
<nuxt-link <nuxt-link
v-else-if="isValid && !cellUrlOptions?.overlay" v-else-if="isValid && !cellUrlOptions?.overlay"
no-prefetch no-prefetch
no-rel no-rel
class="z-3 text-sm underline hover:opacity-75" class="py-1 z-3 text-sm underline hover:opacity-75"
:to="url" :to="url"
:target="cellUrlOptions?.behavior === 'replace' ? undefined : '_blank'" :target="cellUrlOptions?.behavior === 'replace' ? undefined : '_blank'"
:tabindex="readOnly ? -1 : 0"
> >
<LazyCellClampedText :value="value" :lines="rowHeight" /> <LazyCellClampedText :value="value" :lines="rowHeight" class="nc-cell-field" />
</nuxt-link> </nuxt-link>
<nuxt-link <nuxt-link
v-else-if="isValid && !disableOverlay && cellUrlOptions?.overlay" v-else-if="isValid && !disableOverlay && cellUrlOptions?.overlay"
no-prefetch no-prefetch
no-rel no-rel
class="z-3 w-full h-full text-center !no-underline hover:opacity-75" class="py-1 z-3 w-full h-full text-center !no-underline hover:opacity-75"
:to="url" :to="url"
:target="cellUrlOptions?.behavior === 'replace' ? undefined : '_blank'" :target="cellUrlOptions?.behavior === 'replace' ? undefined : '_blank'"
:tabindex="readOnly ? -1 : 0"
> >
<LazyCellClampedText :value="cellUrlOptions.overlay" :lines="rowHeight" /> <LazyCellClampedText :value="cellUrlOptions.overlay" :lines="rowHeight" class="nc-cell-field" />
</nuxt-link> </nuxt-link>
<span v-else class="w-9/10 overflow-ellipsis overflow-hidden"><LazyCellClampedText :value="value" :lines="rowHeight" /></span> <span v-else class="w-9/10 overflow-ellipsis overflow-hidden"
><LazyCellClampedText :value="value" :lines="rowHeight" class="nc-cell-field"
/></span>
<div v-if="column.meta?.validate && !isValid && value?.length && !editEnabled" class="mr-1 w-1/10"> <div v-if="column.meta?.validate && !isValid && value?.length && !editEnabled" class="mr-1 w-1/10">
<a-tooltip placement="top"> <a-tooltip placement="top">

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

@ -9,7 +9,6 @@ import {
ColumnInj, ColumnInj,
EditColumnInj, EditColumnInj,
EditModeInj, EditModeInj,
IsExpandedFormOpenInj,
IsKanbanInj, IsKanbanInj,
ReadonlyInj, ReadonlyInj,
RowHeightInj, RowHeightInj,
@ -49,8 +48,6 @@ const isEditable = inject(EditModeInj, ref(false))
const activeCell = inject(ActiveCellInj, ref(false)) const activeCell = inject(ActiveCellInj, ref(false))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const basesStore = useBases() const basesStore = useBases()
const { basesUser } = storeToRefs(basesStore) const { basesUser } = storeToRefs(basesStore)
@ -265,8 +262,8 @@ const filterOption = (input: string, option: any) => {
<template> <template>
<div <div
class="nc-user-select h-full w-full flex items-center" class="nc-cell-field nc-user-select h-full w-full flex items-center"
:class="{ 'read-only': readOnly, 'px-2': isExpandedFormOpen }" :class="{ 'read-only': readOnly }"
@click="toggleMenu" @click="toggleMenu"
> >
<div <div

7
packages/nc-gui/components/cell/YearPicker.vue

@ -3,7 +3,6 @@ import dayjs from 'dayjs'
import { import {
ActiveCellInj, ActiveCellInj,
EditColumnInj, EditColumnInj,
IsExpandedFormOpenInj,
ReadonlyInj, ReadonlyInj,
computed, computed,
inject, inject,
@ -32,8 +31,6 @@ const editable = inject(EditModeInj, ref(false))
const isEditColumn = inject(EditColumnInj, ref(false)) const isEditColumn = inject(EditColumnInj, ref(false))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const isYearInvalid = ref(false) const isYearInvalid = ref(false)
const { t } = useI18n() const { t } = useI18n()
@ -119,8 +116,8 @@ useSelectedCellKeyupListener(active, (e: KeyboardEvent) => {
:tabindex="0" :tabindex="0"
picker="year" picker="year"
:bordered="false" :bordered="false"
class="!w-full !py-1 !border-none !text-current" class="nc-cell-field !w-full !py-1 !border-none !text-current"
:class="{ 'nc-null': modelValue === null && showNull, '!px-2': isExpandedFormOpen, '!px-0': !isExpandedFormOpen }" :class="{ 'nc-null': modelValue === null && showNull }"
:placeholder="placeholder" :placeholder="placeholder"
:allow-clear="(!readOnly && !localState && !isPk) || isEditColumn" :allow-clear="(!readOnly && !localState && !isPk) || isEditColumn"
:input-read-only="true" :input-read-only="true"

2
packages/nc-gui/components/dashboard/TreeView/ViewsNode.vue

@ -222,7 +222,7 @@ watch(isDropdownOpen, async () => {
:emoji="props.view?.meta?.icon" :emoji="props.view?.meta?.icon"
size="small" size="small"
:clearable="true" :clearable="true"
:readonly="isMobileMode" :readonly="isMobileMode || !isUIAllowed('viewCreateOrEdit')"
@emoji-selected="emits('selectIcon', $event)" @emoji-selected="emits('selectIcon', $event)"
> >
<template #default> <template #default>

4
packages/nc-gui/components/smartsheet/Cell.vue

@ -273,4 +273,8 @@ onUnmounted(() => {
text-align: right; text-align: right;
} }
} }
.nc-cell .nc-cell-field {
@apply px-0;
}
</style> </style>

8
packages/nc-gui/components/smartsheet/column/EditOrAdd.vue

@ -260,7 +260,7 @@ if (props.fromTableExplorer) {
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<a-form-item v-if="isFieldsTab" v-bind="validateInfos.title" class="flex flex-grow"> <a-form-item v-if="isFieldsTab" v-bind="validateInfos.title" class="flex flex-grow">
<div <div
class="flex flex-grow px-2 py-1 items-center rounded-lg bg-gray-100 focus:bg-gray-100 outline-none" class="flex flex-grow px-2 py-1 items-center rounded-md bg-gray-100 focus:bg-gray-100 outline-none"
style="outline-style: solid; outline-width: thin" style="outline-style: solid; outline-width: thin"
> >
<input <input
@ -281,7 +281,7 @@ if (props.fromTableExplorer) {
<a-input <a-input
ref="antInput" ref="antInput"
v-model:value="formState.title" v-model:value="formState.title"
class="nc-column-name-input !rounded !mt-1" class="nc-column-name-input !rounded-md !mt-1"
:disabled="isKanban || readOnly" :disabled="isKanban || readOnly"
@input="onAlter(8)" @input="onAlter(8)"
/> />
@ -297,7 +297,7 @@ if (props.fromTableExplorer) {
<a-select <a-select
v-model:value="formState.uidt" v-model:value="formState.uidt"
show-search show-search
class="nc-column-type-input !rounded" class="nc-column-type-input !rounded-md"
:disabled="isKanban || readOnly" :disabled="isKanban || readOnly"
dropdown-class-name="nc-dropdown-column-type border-1 !rounded-md border-gray-200" dropdown-class-name="nc-dropdown-column-type border-1 !rounded-md border-gray-200"
@dropdown-visible-change="onDropdownChange" @dropdown-visible-change="onDropdownChange"
@ -450,7 +450,7 @@ if (props.fromTableExplorer) {
<style lang="scss"> <style lang="scss">
.nc-column-type-input { .nc-column-type-input {
.ant-select-selector { .ant-select-selector {
@apply !rounded; @apply !rounded-md;
} }
} }
</style> </style>

12
packages/nc-gui/components/smartsheet/column/LinkOptions.vue

@ -52,13 +52,21 @@ vModel.value.meta = {
<a-row class="my-2" gutter="8"> <a-row class="my-2" gutter="8">
<a-col :span="12"> <a-col :span="12">
<a-form-item v-bind="validateInfos['meta.singular']" :label="$t('labels.singularLabel')"> <a-form-item v-bind="validateInfos['meta.singular']" :label="$t('labels.singularLabel')">
<a-input v-model:value="vModel.meta.singular" :placeholder="$t('general.link')" class="!w-full nc-link-singular" /> <a-input
v-model:value="vModel.meta.singular"
:placeholder="$t('general.link')"
class="!w-full nc-link-singular !rounded-md"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="12"> <a-col :span="12">
<a-form-item v-bind="validateInfos['meta.plural']" :label="$t('labels.pluralLabel')"> <a-form-item v-bind="validateInfos['meta.plural']" :label="$t('labels.pluralLabel')">
<a-input v-model:value="vModel.meta.plural" :placeholder="$t('general.links')" class="!w-full nc-link-plural" /> <a-input
v-model:value="vModel.meta.plural"
:placeholder="$t('general.links')"
class="!w-full nc-link-plural !rounded-md"
/>
</a-form-item> </a-form-item>
</a-col> </a-col>
</a-row> </a-row>

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

@ -570,7 +570,7 @@ export default {
{{ isRecordLinkCopied ? $t('labels.copiedRecordURL') : $t('labels.copyRecordURL') }} {{ isRecordLinkCopied ? $t('labels.copiedRecordURL') : $t('labels.copyRecordURL') }}
</div> </div>
</NcButton> </NcButton>
<NcDropdown v-if="!isNew" placement="bottomRight"> <NcDropdown v-if="!isNew && rowId" placement="bottomRight">
<NcButton type="secondary" class="nc-expand-form-more-actions w-10" :disabled="isLoading"> <NcButton type="secondary" class="nc-expand-form-more-actions w-10" :disabled="isLoading">
<GeneralIcon icon="threeDotVertical" class="text-md" :class="isLoading ? 'text-gray-300' : 'text-gray-700'" /> <GeneralIcon icon="threeDotVertical" class="text-md" :class="isLoading ? 'text-gray-300' : 'text-gray-700'" />
</NcButton> </NcButton>
@ -698,7 +698,7 @@ export default {
:ref="i ? null : (el: any) => (cellWrapperEl = el)" :ref="i ? null : (el: any) => (cellWrapperEl = el)"
class="bg-white w-80 xs:w-full px-1 sm:min-h-[35px] xs:min-h-13 flex items-center relative" class="bg-white w-80 xs:w-full px-1 sm:min-h-[35px] xs:min-h-13 flex items-center relative"
:class="{ :class="{
'!bg-gray-50 !px-0 !select-text nc-system-field': isReadOnlyVirtualCell(col), '!bg-gray-50 !select-text nc-system-field': isReadOnlyVirtualCell(col),
}" }"
> >
<LazySmartsheetVirtualCell <LazySmartsheetVirtualCell
@ -946,4 +946,13 @@ export default {
:deep(.nc-system-field input) { :deep(.nc-system-field input) {
@apply bg-transparent; @apply bg-transparent;
} }
:deep(.nc-data-cell .nc-cell .nc-cell-field) {
@apply px-2;
}
:deep(.nc-data-cell .nc-virtual-cell .nc-cell-field) {
@apply px-2;
}
:deep(.nc-data-cell .nc-cell-field.nc-lookup-cell .nc-cell-field) {
@apply px-0;
}
</style> </style>

2
packages/nc-gui/components/smartsheet/header/CellIcon.ts

@ -125,7 +125,7 @@ export default defineComponent({
if (!column.value && !columnMeta.value) return null if (!column.value && !columnMeta.value) return null
return h(renderIcon((columnMeta.value ?? column.value)!, abstractType.value), { return h(renderIcon((columnMeta.value ?? column.value)!, abstractType.value), {
class: 'text-inherit mx-1', class: 'text-inherit mx-1 nc-cell-icon',
}) })
} }
}, },

2
packages/nc-gui/components/smartsheet/header/VirtualCellIcon.ts

@ -104,7 +104,7 @@ export default defineComponent({
const { icon: Icon, color } = renderIcon(column.value, relationColumn) const { icon: Icon, color } = renderIcon(column.value, relationColumn)
return h(Icon, { class: `${color} mx-1` }) return h(Icon, { class: `${color} mx-1 nc-virtual-cell-icon` })
} }
}, },
}) })

8
packages/nc-gui/components/smartsheet/toolbar/SortListMenu.vue

@ -130,11 +130,7 @@ onMounted(() => {
class="py-6 pl-6 nc-filter-list max-h-[max(80vh,30rem)]" class="py-6 pl-6 nc-filter-list max-h-[max(80vh,30rem)]"
data-testid="nc-sorts-menu" data-testid="nc-sorts-menu"
> >
<div <div class="sort-grid max-h-120 nc-scrollbar-md" :class="{ 'pr-3.5': sorts?.length }" @click.stop>
class="sort-grid max-h-120 nc-scrollbar-md"
:class="{ 'pb-3 pr-3.5': sorts?.length, '!pb-0': !availableColumns.length }"
@click.stop
>
<template v-for="(sort, i) of sorts" :key="i"> <template v-for="(sort, i) of sorts" :key="i">
<SmartsheetToolbarFieldListAutoCompleteDropdown <SmartsheetToolbarFieldListAutoCompleteDropdown
v-model="sort.fk_column_id" v-model="sort.fk_column_id"
@ -187,6 +183,7 @@ onMounted(() => {
v-if="availableColumns.length" v-if="availableColumns.length"
v-model:visible="showCreateSort" v-model:visible="showCreateSort"
:trigger="['click']" :trigger="['click']"
class="mt-3"
overlay-class-name="nc-toolbar-dropdown" overlay-class-name="nc-toolbar-dropdown"
> >
<template v-if="isEeUI && !isPublic"> <template v-if="isEeUI && !isPublic">
@ -204,6 +201,7 @@ onMounted(() => {
{{ $t('activity.addSort') }} {{ $t('activity.addSort') }}
</div> </div>
</NcButton> </NcButton>
<span v-else></span>
</template> </template>
<template v-else> <template v-else>
<NcButton v-e="['c:sort:add']" class="!text-brand-500" type="text" size="small" @click.stop="showCreateSort = true"> <NcButton v-e="['c:sort:add']" class="!text-brand-500" type="text" size="small" @click.stop="showCreateSort = true">

2
packages/nc-gui/components/virtual-cell/BelongsTo.vue

@ -95,7 +95,7 @@ watch([listItemsDlg], () => {
<template> <template>
<div class="flex w-full chips-wrapper items-center" :class="{ active }"> <div class="flex w-full chips-wrapper items-center" :class="{ active }">
<div class="chips flex items-center flex-1"> <div class="nc-cell-field chips flex items-center flex-1">
<template v-if="value && relatedTableDisplayValueProp"> <template v-if="value && relatedTableDisplayValueProp">
<VirtualCellComponentsItemChip <VirtualCellComponentsItemChip
:item="value" :item="value"

24
packages/nc-gui/components/virtual-cell/Formula.vue

@ -2,24 +2,13 @@
import { handleTZ } from 'nocodb-sdk' import { handleTZ } from 'nocodb-sdk'
import type { ColumnType } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { import { CellValueInj, ColumnInj, computed, inject, renderValue, replaceUrlsWithLink, useBase } from '#imports'
CellValueInj,
ColumnInj,
IsExpandedFormOpenInj,
computed,
inject,
renderValue,
replaceUrlsWithLink,
useBase,
} from '#imports'
// todo: column type doesn't have required property `error` - throws in typecheck // todo: column type doesn't have required property `error` - throws in typecheck
const column = inject(ColumnInj) as Ref<ColumnType & { colOptions: { error: any } }> const column = inject(ColumnInj) as Ref<ColumnType & { colOptions: { error: any } }>
const cellValue = inject(CellValueInj) const cellValue = inject(CellValueInj)
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const { isPg } = useBase() const { isPg } = useBase()
const result = computed(() => const result = computed(() =>
@ -40,15 +29,8 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning, activ
</template> </template>
<span>ERR!</span> <span>ERR!</span>
</a-tooltip> </a-tooltip>
<span v-else-if="cellValue === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span>
<div <div v-else class="nc-cell-field py-1" @dblclick="activateShowEditNonEditableFieldWarning">
v-else
class="py-1"
:class="{
'px-2': isExpandedFormOpen,
}"
@dblclick="activateShowEditNonEditableFieldWarning"
>
<div v-if="urls" v-html="urls" /> <div v-if="urls" v-html="urls" />
<div v-else>{{ result }}</div> <div v-else>{{ result }}</div>

24
packages/nc-gui/components/virtual-cell/Links.vue

@ -3,15 +3,7 @@ import { computed } from '@vue/reactivity'
import type { ColumnType } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import { ref } from 'vue' import { ref } from 'vue'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { import { ActiveCellInj, CellValueInj, ColumnInj, IsUnderLookupInj, inject, useSelectedCellKeyupListener } from '#imports'
ActiveCellInj,
CellValueInj,
ColumnInj,
IsExpandedFormOpenInj,
IsUnderLookupInj,
inject,
useSelectedCellKeyupListener,
} from '#imports'
const value = inject(CellValueInj, ref(0)) const value = inject(CellValueInj, ref(0))
@ -27,8 +19,6 @@ const readOnly = inject(ReadonlyInj, ref(false))
const isUnderLookup = inject(IsUnderLookupInj, ref(false)) const isUnderLookup = inject(IsUnderLookupInj, ref(false))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const colTitle = computed(() => column.value?.title || '') const colTitle = computed(() => column.value?.title || '')
const listItemsDlg = ref(false) const listItemsDlg = ref(false)
@ -130,13 +120,7 @@ watch([listItemsDlg], () => {
</script> </script>
<template> <template>
<div <div class="nc-cell-field flex w-full group items-center nc-links-wrapper py-1" @dblclick.stop="openChildList">
class="flex w-full group items-center nc-links-wrapper py-1"
:class="{
'px-2': isExpandedFormOpen,
}"
@dblclick.stop="openChildList"
>
<div class="block flex-shrink truncate"> <div class="block flex-shrink truncate">
<component <component
:is="isUnderLookup ? 'span' : 'a'" :is="isUnderLookup ? 'span' : 'a'"
@ -145,7 +129,7 @@ watch([listItemsDlg], () => {
:title="textVal" :title="textVal"
class="text-center nc-datatype-link underline-transparent" class="text-center nc-datatype-link underline-transparent"
:class="{ '!text-gray-300': !textVal }" :class="{ '!text-gray-300': !textVal }"
tabindex="0" :tabindex="readOnly ? -1 : 0"
@click.stop.prevent="openChildList" @click.stop.prevent="openChildList"
@keydown.enter.stop.prevent="openChildList" @keydown.enter.stop.prevent="openChildList"
> >
@ -157,7 +141,7 @@ watch([listItemsDlg], () => {
<div <div
v-if="!isUnderLookup" v-if="!isUnderLookup"
ref="plusBtnRef" ref="plusBtnRef"
tabindex="0" :tabindex="readOnly ? -1 : 0"
class="!xs:hidden flex group justify-end group-hover:flex items-center" class="!xs:hidden flex group justify-end group-hover:flex items-center"
@keydown.enter.stop="openListDlg" @keydown.enter.stop="openListDlg"
> >

4
packages/nc-gui/components/virtual-cell/Lookup.vue

@ -100,7 +100,7 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning, activ
<template> <template>
<div <div
class="h-full w-full nc-lookup-cell" class="nc-cell-field h-full w-full nc-lookup-cell"
tabindex="-1" tabindex="-1"
:style="{ height: isGroupByLabel ? undefined : rowHeight && rowHeight !== 1 ? `${rowHeight * 2}rem` : `2.85rem` }" :style="{ height: isGroupByLabel ? undefined : rowHeight && rowHeight !== 1 ? `${rowHeight * 2}rem` : `2.85rem` }"
@dblclick="activateShowEditNonEditableFieldWarning" @dblclick="activateShowEditNonEditableFieldWarning"
@ -185,7 +185,7 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning, activ
:read-only="true" :read-only="true"
:class="{ :class="{
'min-h-0 min-w-0': isAttachment(lookupColumn), 'min-h-0 min-w-0': isAttachment(lookupColumn),
'!min-w-20 !w-auto pl-2': !isAttachment(lookupColumn), '!min-w-20 !w-auto px-2': !isAttachment(lookupColumn),
}" }"
/> />
</div> </div>

2
packages/nc-gui/components/virtual-cell/Rollup.vue

@ -41,7 +41,7 @@ const childColumn = computed(() => {
</script> </script>
<template> <template>
<div @dblclick="activateShowEditNonEditableFieldWarning"> <div class="nc-cell-field" @dblclick="activateShowEditNonEditableFieldWarning">
<div v-if="['count', 'avg', 'sum', 'countDistinct', 'sumDistinct', 'avgDistinct'].includes(colOptions.rollup_function)"> <div v-if="['count', 'avg', 'sum', 'countDistinct', 'sumDistinct', 'avgDistinct'].includes(colOptions.rollup_function)">
{{ value }} {{ value }}
</div> </div>

6
packages/nc-gui/components/virtual-cell/barcode/Barcode.vue

@ -90,13 +90,13 @@ const rowHeight = inject(RowHeightInj, ref(undefined))
</JsBarcodeWrapper> </JsBarcodeWrapper>
</div> </div>
<div v-if="tooManyCharsForBarcode" class="text-left text-wrap mt-2 text-[#e65100] text-xs"> <div v-if="tooManyCharsForBarcode" class="nc-cell-field text-left text-wrap text-[#e65100] text-xs">
{{ $t('labels.barcodeValueTooLong') }} {{ $t('labels.barcodeValueTooLong') }}
</div> </div>
<div v-if="showEditNonEditableFieldWarning" class="text-left text-wrap mt-2 text-[#e65100] text-xs"> <div v-if="showEditNonEditableFieldWarning" class="nc-cell-field text-left text-wrap mt-2 text-[#e65100] text-xs">
{{ $t('msg.warning.nonEditableFields.computedFieldUnableToClear') }} {{ $t('msg.warning.nonEditableFields.computedFieldUnableToClear') }}
</div> </div>
<div v-if="showClearNonEditableFieldWarning" class="text-left text-wrap mt-2 text-[#e65100] text-xs"> <div v-if="showClearNonEditableFieldWarning" class="nc-cell-field text-left text-wrap mt-2 text-[#e65100] text-xs">
{{ $t('msg.warning.nonEditableFields.barcodeFieldsCannotBeDirectlyChanged') }} {{ $t('msg.warning.nonEditableFields.barcodeFieldsCannotBeDirectlyChanged') }}
</div> </div>
</template> </template>

10
packages/nc-gui/components/virtual-cell/components/ListChildItems.vue

@ -39,7 +39,7 @@ const isPublic = inject(IsPublicInj, ref(false))
const injectedColumn = inject(ColumnInj, ref()) const injectedColumn = inject(ColumnInj, ref())
const readonly = inject(ReadonlyInj, ref(false)) const readOnly = inject(ReadonlyInj, ref(false))
const { isSharedBase } = storeToRefs(useBase()) const { isSharedBase } = storeToRefs(useBase())
@ -107,7 +107,7 @@ const expandedFormRow = ref({})
const colTitle = computed(() => injectedColumn.value?.title || '') const colTitle = computed(() => injectedColumn.value?.title || '')
const onClick = (row: Row) => { const onClick = (row: Row) => {
if (readonly.value) return if (readOnly.value) return
expandedFormRow.value = row expandedFormRow.value = row
expandedFormDlg.value = true expandedFormDlg.value = true
} }
@ -166,7 +166,7 @@ const isDataExist = computed<boolean>(() => {
const linkOrUnLink = (rowRef: Record<string, string>, id: string) => { const linkOrUnLink = (rowRef: Record<string, string>, id: string) => {
if (isSharedBase.value) return if (isSharedBase.value) return
if (readonly.value) return if (readOnly.value) return
if (isPublic.value && !isForm.value) return if (isPublic.value && !isForm.value) return
if (isNew.value || isChildrenListLinked.value[parseInt(id)]) { if (isNew.value || isChildrenListLinked.value[parseInt(id)]) {
@ -276,7 +276,7 @@ const linkOrUnLink = (rowRef: Record<string, string>, id: string) => {
{{ relatedTableMeta?.title }} {{ relatedTableMeta?.title }}
</p> </p>
<NcButton <NcButton
v-if="!readonly && childrenListCount < 1" v-if="!readOnly && childrenListCount < 1"
v-e="['c:links:link']" v-e="['c:links:link']"
data-testid="nc-child-list-button-link-to" data-testid="nc-child-list-button-link-to"
@click="emit('attachRecord')" @click="emit('attachRecord')"
@ -322,7 +322,7 @@ const linkOrUnLink = (rowRef: Record<string, string>, id: string) => {
<div class="flex flex-row gap-2"> <div class="flex flex-row gap-2">
<NcButton v-if="!isForm" type="ghost" class="nc-close-btn" @click="vModel = false"> {{ $t('general.finish') }} </NcButton> <NcButton v-if="!isForm" type="ghost" class="nc-close-btn" @click="vModel = false"> {{ $t('general.finish') }} </NcButton>
<NcButton <NcButton
v-if="!readonly && childrenListCount > 0" v-if="!readOnly && childrenListCount > 0"
v-e="['c:links:link']" v-e="['c:links:link']"
data-testid="nc-child-list-button-link-to" data-testid="nc-child-list-button-link-to"
@click="emit('attachRecord')" @click="emit('attachRecord')"

11
packages/nc-gui/components/virtual-cell/components/ListItem.vue

@ -5,6 +5,7 @@ import {
IsExpandedFormOpenInj, IsExpandedFormOpenInj,
IsFormInj, IsFormInj,
IsPublicInj, IsPublicInj,
ReadonlyInj,
RowHeightInj, RowHeightInj,
computed, computed,
inject, inject,
@ -39,7 +40,7 @@ const row = useVModel(props, 'row')
const isPublic = inject(IsPublicInj, ref(false)) const isPublic = inject(IsPublicInj, ref(false))
const readonly = inject(ReadonlyInj, ref(false)) const readOnly = inject(ReadonlyInj, ref(false))
const { getPossibleAttachmentSrc } = useAttachment() const { getPossibleAttachmentSrc } = useAttachment()
@ -93,7 +94,7 @@ const displayValue = computed(() => {
'!bg-white': isLoading, '!bg-white': isLoading,
'!border-1': isLinked && !isLoading, '!border-1': isLinked && !isLoading,
'!hover:border-gray-400': !isLinked, '!hover:border-gray-400': !isLinked,
'!cursor-auto !hover:bg-white': readonly, '!cursor-auto !hover:bg-white': readOnly,
}" }"
:body-style="{ padding: 0 }" :body-style="{ padding: 0 }"
:hoverable="false" :hoverable="false"
@ -126,7 +127,7 @@ const displayValue = computed(() => {
v-if="isLinked && !isLoading" v-if="isLinked && !isLoading"
class="text-brand-500 text-0.875" class="text-brand-500 text-0.875"
:class="{ :class="{
'!group-hover:mr-12': fields.length === 0 && !readonly, '!group-hover:mr-12': fields.length === 0 && !readOnly,
}" }"
> >
<LinkIcon class="w-4 h-4" /> <LinkIcon class="w-4 h-4" />
@ -135,7 +136,7 @@ const displayValue = computed(() => {
<MdiLoading <MdiLoading
v-else-if="isLoading" v-else-if="isLoading"
:class="{ :class="{
'!group-hover:mr-8': fields.length === 0 && !readonly, '!group-hover:mr-8': fields.length === 0 && !readOnly,
}" }"
class="w-6 h-6 !text-brand-500 animate-spin" class="w-6 h-6 !text-brand-500 animate-spin"
/> />
@ -174,7 +175,7 @@ const displayValue = computed(() => {
</div> </div>
</div> </div>
<NcButton <NcButton
v-if="!isForm && !isPublic && !readonly" v-if="!isForm && !isPublic && !readOnly"
v-e="['c:row-expand:open']" v-e="['c:row-expand:open']"
type="text" type="text"
size="lg" size="lg"

2
packages/nc-gui/composables/useColumnCreateStore.ts

@ -114,6 +114,7 @@ const [useProvideColumnCreateStore, useColumnCreateStore] = createInjectionState
validator: (rule: any, value: any) => { validator: (rule: any, value: any) => {
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
if ( if (
value !== '' &&
(tableExplorerColumns?.value || meta.value?.columns)?.some( (tableExplorerColumns?.value || meta.value?.columns)?.some(
(c) => (c) =>
c.id !== formState.value.id && // ignore current column c.id !== formState.value.id && // ignore current column
@ -126,6 +127,7 @@ const [useProvideColumnCreateStore, useColumnCreateStore] = createInjectionState
return reject(new Error(t('msg.error.duplicateSystemColumnName'))) return reject(new Error(t('msg.error.duplicateSystemColumnName')))
} }
if ( if (
value !== '' &&
(tableExplorerColumns?.value || meta.value?.columns)?.some( (tableExplorerColumns?.value || meta.value?.columns)?.some(
(c) => (c) =>
c.id !== formState.value.id && // ignore current column c.id !== formState.value.id && // ignore current column

Loading…
Cancel
Save