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) {
@apply !xs:(hidden)
@apply !xs:(hidden);
}
}
@ -727,13 +727,18 @@ input[type='number'] {
@apply xs:(opacity-100 hover:bg-gray-50);
.nc-icon {
@apply xs:(visible opacity-100 !text-gray-500)
@apply xs:(visible opacity-100 !text-gray-500);
}
}
.ant-message-notice-content {
@apply !rounded-md;
.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,
'nc-cell-hover-show': !vModel && !readOnly,
'opacity-0': readOnly && !vModel,
'pointer-events-none': readOnly,
}"
:style="{
height:
isForm || isExpandedFormOpen || isGallery || isEditColumnMenu ? undefined : `max(${(rowHeight || 1) * 1.8}rem, 41px)`,
}"
tabindex="0"
:tabindex="readOnly ? -1 : 0"
@click="onClick(false, $event)"
@keydown.enter.stop="onClick(true, $event)"
>

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

@ -6,6 +6,7 @@ import {
EditModeInj,
IsExpandedFormOpenInj,
IsFormInj,
ReadonlyInj,
computed,
inject,
parseProp,
@ -28,6 +29,8 @@ const editEnabled = inject(EditModeInj)!
const isEditColumn = inject(EditColumnInj, ref(false))
const readOnly = inject(ReadonlyInj, ref(false))
const _vModel = useVModel(props, 'modelValue', emit)
const vModel = computed({
@ -87,12 +90,11 @@ onMounted(() => {
<template>
<input
v-if="editEnabled"
v-if="!readOnly && editEnabled"
:ref="focus"
v-model="vModel"
type="number"
class="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'"
class="nc-cell-field w-full h-full text-sm border-none rounded-md py-1 outline-none focus:outline-none focus:ring-0"
:placeholder="isEditColumn ? $t('labels.optional') : ''"
@blur="submitCurrency"
@keydown.down.stop
@ -105,10 +107,10 @@ onMounted(() => {
@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 -->
<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 -->
<span v-else />

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

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

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

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

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

@ -1,6 +1,6 @@
<script lang="ts" setup>
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 {
// 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 readOnly = inject(ReadonlyInj, ref(false))
const domRef = ref<HTMLElement>()
const meta = computed(() => {
@ -94,11 +96,10 @@ watch(isExpandedFormOpen, () => {
<template>
<input
v-if="editEnabled"
v-if="!readOnly && editEnabled"
:ref="focus"
v-model="vModel"
class="outline-none py-1 border-none rounded-md w-full h-full !text-sm"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
class="nc-cell-field outline-none py-1 border-none rounded-md w-full h-full !text-sm"
type="number"
:step="precision"
:placeholder="isEditColumn ? $t('labels.optional') : ''"
@ -112,8 +113,8 @@ watch(isExpandedFormOpen, () => {
@selectstart.capture.stop
@mousedown.stop
/>
<span v-else-if="vModel === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span>
<span v-else class="text-sm">{{ displayValue }}</span>
<span v-else-if="vModel === null && showNull" class="nc-cell-field nc-null uppercase">{{ $t('general.null') }}</span>
<span v-else class="nc-cell-field text-sm">{{ displayValue }}</span>
</template>
<style scoped lang="scss">

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

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

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

@ -6,6 +6,7 @@ import {
IsExpandedFormOpenInj,
IsFormInj,
IsSurveyFormInj,
ReadonlyInj,
computed,
inject,
useI18n,
@ -30,13 +31,15 @@ const editEnabled = inject(EditModeInj)!
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 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({
get: () => value,
set: (val) => {
@ -71,11 +74,10 @@ watch(
<template>
<input
v-if="editEnabled"
v-if="!readOnly && editEnabled"
:ref="focus"
v-model="vModel"
class="w-full outline-none text-sm py-1"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
class="nc-cell-field w-full outline-none text-sm py-1"
:placeholder="isEditColumn ? $t('labels.optional') : ''"
@blur="editEnabled = false"
@keydown.down.stop
@ -87,17 +89,18 @@ watch(
@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
v-else-if="validEmail"
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}`"
target="_blank"
:tabindex="readOnly ? -1 : 0"
>
<LazyCellClampedText :value="vModel" :lines="rowHeight" />
<LazyCellClampedText :value="vModel" :lines="rowHeight" class="nc-cell-field" />
</nuxt-link>
<LazyCellClampedText v-else :value="vModel" :lines="rowHeight" />
<LazyCellClampedText v-else :value="vModel" :lines="rowHeight" class="nc-cell-field" />
</template>

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

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

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

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

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

@ -1,6 +1,6 @@
<script setup lang="ts">
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 {
// 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 readOnly = inject(ReadonlyInj, ref(false))
const _vModel = useVModel(props, 'modelValue', emits)
const displayValue = computed(() => {
@ -85,11 +87,10 @@ function onKeyDown(e: any) {
<template>
<input
v-if="editEnabled"
v-if="!readOnly && editEnabled"
:ref="focus"
v-model="vModel"
class="outline-none py-1 border-none w-full h-full text-sm"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
class="nc-cell-field outline-none py-1 border-none w-full h-full text-sm"
type="number"
style="letter-spacing: 0.06rem"
:placeholder="isEditColumn ? $t('labels.optional') : ''"
@ -103,8 +104,8 @@ function onKeyDown(e: any) {
@selectstart.capture.stop
@mousedown.stop
/>
<span v-else-if="vModel === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span>
<span v-else class="text-sm">{{ displayValue }}</span>
<span v-else-if="vModel === null && showNull" class="nc-cell-field nc-null uppercase">{{ $t('general.null') }}</span>
<span v-else class="nc-cell-field text-sm">{{ displayValue }}</span>
</template>
<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 readonly = inject(ReadonlyInj)
const readOnly = inject(ReadonlyInj, ref(false))
const vModel = useVModel(props, 'modelValue', emits)
@ -158,7 +158,7 @@ watch(isExpanded, () => {
:footer="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>
<a-button type="text" size="small" @click="isExpanded = !isExpanded">
<CilFullscreenExit v-if="isExpanded" class="h-2.5" />
@ -187,14 +187,14 @@ watch(isExpanded, () => {
@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() }}
</span>
</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>
</template>

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

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

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

@ -1,6 +1,6 @@
<script setup lang="ts">
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 {
modelValue?: number | string | null
@ -14,10 +14,12 @@ const { showNull } = useGlobal()
const column = inject(ColumnInj)!
const editEnabled = inject(EditModeInj)
const editEnabled = inject(EditModeInj, ref(false))
const isEditColumn = inject(EditColumnInj, ref(false))
const readOnly = inject(ReadonlyInj, ref(false))
const _vModel = useVModel(props, 'modelValue', emits)
const wrapperRef = ref<HTMLElement>()
@ -118,18 +120,18 @@ const onTabPress = (e: KeyboardEvent) => {
<template>
<div
ref="wrapperRef"
tabindex="0"
:tabindex="readOnly ? -1 : 0"
class="nc-filter-value-select w-full focus:outline-transparent"
:class="readOnly ? 'cursor-not-allowed pointer-events-none' : ''"
@mouseover="onMouseover"
@mouseleave="onMouseleave"
@focus="onWrapperFocus"
>
<input
v-if="editEnabled"
v-if="!readOnly && editEnabled && (isExpandedFormOpen ? expandedEditEnabled : true)"
:ref="focus"
v-model="vModel"
class="w-full !text-sm !border-none !outline-none focus:ring-0 text-base py-1"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
class="nc-cell-field w-full !text-sm !border-none !outline-none focus:ring-0 text-base py-1"
type="number"
:placeholder="isEditColumn ? $t('labels.optional') : ''"
@blur="onBlur"
@ -143,7 +145,7 @@ const onTabPress = (e: KeyboardEvent) => {
@selectstart.capture.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">
<a-progress
:percent="Number(parseFloat(vModel.toString()).toFixed(2))"
@ -155,7 +157,7 @@ const onTabPress = (e: KeyboardEvent) => {
/>
</div>
<!-- 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>
</template>

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

@ -17,17 +17,19 @@ const { showNull } = useGlobal()
const { t } = useI18n()
const editEnabled = inject(EditModeInj)!
const editEnabled = inject(EditModeInj, ref(false))
const isEditColumn = inject(EditColumnInj, ref(false))
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
const localState = ref(value)
const isSurveyForm = inject(IsSurveyFormInj, ref(false))
const vModel = computed({
get: () => value,
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))!
@ -62,11 +64,10 @@ watch(
<template>
<input
v-if="editEnabled"
v-if="!readOnly && editEnabled"
:ref="focus"
v-model="vModel"
class="w-full outline-none text-sm py-1"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
class="nc-cell-field w-full outline-none text-sm py-1"
:placeholder="isEditColumn ? $t('labels.optional') : ''"
@blur="editEnabled = false"
@keydown.down.stop
@ -78,17 +79,18 @@ watch(
@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
v-else-if="validEmail"
class="text-sm underline hover:opacity-75"
v-else-if="validPhoneNumber"
class="py-1 text-sm underline hover:opacity-75 inline-block"
:href="`tel:${vModel}`"
target="_blank"
rel="noopener noreferrer"
:tabindex="readOnly ? -1 : 0"
>
<LazyCellClampedText :value="vModel" :lines="rowHeight" />
<LazyCellClampedText :value="vModel" :lines="rowHeight" class="nc-cell-field" />
</a>
<LazyCellClampedText v-else :value="vModel" :lines="rowHeight" />
<LazyCellClampedText v-else :value="vModel" :lines="rowHeight" class="nc-cell-field" />
</template>

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

@ -3,6 +3,7 @@ import {
ActiveCellInj,
ColumnInj,
IsExpandedFormOpenInj,
ReadonlyInj,
computed,
inject,
parseProp,
@ -19,7 +20,7 @@ const emits = defineEmits(['update:modelValue'])
const column = inject(ColumnInj)!
const readonly = inject(ReadonlyInj, ref(false))
const readOnly = inject(ReadonlyInj, ref(false))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
@ -73,8 +74,9 @@ watch(rateDomRef, () => {
<a-rate
ref="rateDomRef"
v-model:value="vModel"
:disabled="readonly"
:disabled="readOnly"
:count="ratingMeta.max"
:class="readOnly ? 'pointer-events-none' : ''"
:style="`color: ${ratingMeta.color}; padding: ${isExpandedFormOpen ? '0px 8px' : '0px 5px'};`"
@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 { TaskItem } from '@/helpers/dbTiptapExtensions/task-item'
import { Link } from '@/helpers/dbTiptapExtensions/links'
import { IsExpandedFormOpenInj, RowHeightInj } from '#imports'
import { IsExpandedFormOpenInj, ReadonlyInj, RowHeightInj } from '#imports'
const props = defineProps<{
value?: string | null
@ -24,6 +24,8 @@ const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const rowHeight = inject(RowHeightInj, ref(1 as const))
const readOnlyCell = inject(ReadonlyInj, ref(false))
const turndownService = new TurndownService({})
turndownService.addRule('lineBreak', {
@ -174,7 +176,7 @@ watch(editorDom, () => {
'nc-rich-text-embed flex flex-col pl-1 w-full': !fullMode,
'readonly': readOnly,
}"
tabindex="0"
:tabindex="readOnlyCell ? -1 : 0"
>
<div
v-if="showMenu && !readOnly"

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

@ -8,7 +8,6 @@ import {
ColumnInj,
EditColumnInj,
EditModeInj,
IsExpandedFormOpenInj,
IsFormInj,
IsKanbanInj,
ReadonlyInj,
@ -48,8 +47,6 @@ const activeCell = inject(ActiveCellInj, ref(false))
const isForm = inject(IsFormInj, ref(false))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
// use both ActiveCellInj or EditModeInj to determine the active state
// since active will be false in case of form view
const active = computed(() => activeCell.value || isEditable.value || isForm.value)
@ -274,8 +271,8 @@ const onFocus = () => {
<template>
<div
class="h-full w-full flex items-center nc-single-select focus:outline-transparent"
:class="{ 'read-only': readOnly, 'px-2': isExpandedFormOpen }"
class="nc-cell-field h-full w-full flex items-center nc-single-select focus:outline-transparent"
:class="{ 'read-only': readOnly }"
@click="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 readonly = inject(ReadonlyInj, ref(false))
const readOnly = inject(ReadonlyInj, ref(false))
const vModel = useVModel(props, 'modelValue', emits)
@ -42,11 +42,10 @@ const focus: VNodeRef = (el) =>
<template>
<input
v-if="!readonly && editEnabled"
v-if="!readOnly && editEnabled"
:ref="focus"
v-model="vModel"
class="h-full w-full outline-none py-1 bg-transparent"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
class="nc-cell-field h-full w-full outline-none py-1 bg-transparent"
:placeholder="isEditColumn ? $t('labels.optional') : ''"
@blur="editEnabled = false"
@keydown.down.stop
@ -58,7 +57,7 @@ const focus: VNodeRef = (el) =>
@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>

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

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

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

@ -8,6 +8,7 @@ import {
IsExpandedFormOpenInj,
IsFormInj,
IsSurveyFormInj,
ReadonlyInj,
computed,
inject,
isValidURL,
@ -39,13 +40,15 @@ const isEditColumn = inject(EditColumnInj, 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 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({
get: () => value,
set: (val) => {
@ -92,12 +95,11 @@ watch(
<template>
<div class="flex flex-row items-center justify-between w-full h-full">
<input
v-if="editEnabled"
v-if="!readOnly && editEnabled"
:ref="focus"
v-model="vModel"
:placeholder="isEditColumn ? $t('labels.enterDefaultUrlOptional') : ''"
class="outline-none text-sm w-full py-1 bg-transparent h-full"
:class="isExpandedFormOpen ? 'px-2' : 'px-0'"
class="nc-cell-field outline-none text-sm w-full py-1 bg-transparent h-full"
@blur="editEnabled = false"
@keydown.down.stop
@keydown.left.stop
@ -108,31 +110,35 @@ watch(
@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
v-else-if="isValid && !cellUrlOptions?.overlay"
no-prefetch
no-rel
class="z-3 text-sm underline hover:opacity-75"
class="py-1 z-3 text-sm underline hover:opacity-75"
:to="url"
: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
v-else-if="isValid && !disableOverlay && cellUrlOptions?.overlay"
no-prefetch
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"
: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>
<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">
<a-tooltip placement="top">

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

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

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

@ -3,7 +3,6 @@ import dayjs from 'dayjs'
import {
ActiveCellInj,
EditColumnInj,
IsExpandedFormOpenInj,
ReadonlyInj,
computed,
inject,
@ -32,8 +31,6 @@ const editable = inject(EditModeInj, ref(false))
const isEditColumn = inject(EditColumnInj, ref(false))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const isYearInvalid = ref(false)
const { t } = useI18n()
@ -119,8 +116,8 @@ useSelectedCellKeyupListener(active, (e: KeyboardEvent) => {
:tabindex="0"
picker="year"
:bordered="false"
class="!w-full !py-1 !border-none !text-current"
:class="{ 'nc-null': modelValue === null && showNull, '!px-2': isExpandedFormOpen, '!px-0': !isExpandedFormOpen }"
class="nc-cell-field !w-full !py-1 !border-none !text-current"
:class="{ 'nc-null': modelValue === null && showNull }"
:placeholder="placeholder"
:allow-clear="(!readOnly && !localState && !isPk) || isEditColumn"
: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"
size="small"
:clearable="true"
:readonly="isMobileMode"
:readonly="isMobileMode || !isUIAllowed('viewCreateOrEdit')"
@emoji-selected="emits('selectIcon', $event)"
>
<template #default>

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

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

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

@ -260,7 +260,7 @@ if (props.fromTableExplorer) {
<div class="flex flex-col gap-2">
<a-form-item v-if="isFieldsTab" v-bind="validateInfos.title" class="flex flex-grow">
<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"
>
<input
@ -281,7 +281,7 @@ if (props.fromTableExplorer) {
<a-input
ref="antInput"
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"
@input="onAlter(8)"
/>
@ -297,7 +297,7 @@ if (props.fromTableExplorer) {
<a-select
v-model:value="formState.uidt"
show-search
class="nc-column-type-input !rounded"
class="nc-column-type-input !rounded-md"
:disabled="isKanban || readOnly"
dropdown-class-name="nc-dropdown-column-type border-1 !rounded-md border-gray-200"
@dropdown-visible-change="onDropdownChange"
@ -450,7 +450,7 @@ if (props.fromTableExplorer) {
<style lang="scss">
.nc-column-type-input {
.ant-select-selector {
@apply !rounded;
@apply !rounded-md;
}
}
</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-col :span="12">
<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-col>
<a-col :span="12">
<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-col>
</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') }}
</div>
</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">
<GeneralIcon icon="threeDotVertical" class="text-md" :class="isLoading ? 'text-gray-300' : 'text-gray-700'" />
</NcButton>
@ -698,7 +698,7 @@ export default {
: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-gray-50 !px-0 !select-text nc-system-field': isReadOnlyVirtualCell(col),
'!bg-gray-50 !select-text nc-system-field': isReadOnlyVirtualCell(col),
}"
>
<LazySmartsheetVirtualCell
@ -946,4 +946,13 @@ export default {
:deep(.nc-system-field input) {
@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>

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

@ -125,7 +125,7 @@ export default defineComponent({
if (!column.value && !columnMeta.value) return null
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)
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)]"
data-testid="nc-sorts-menu"
>
<div
class="sort-grid max-h-120 nc-scrollbar-md"
:class="{ 'pb-3 pr-3.5': sorts?.length, '!pb-0': !availableColumns.length }"
@click.stop
>
<div class="sort-grid max-h-120 nc-scrollbar-md" :class="{ 'pr-3.5': sorts?.length }" @click.stop>
<template v-for="(sort, i) of sorts" :key="i">
<SmartsheetToolbarFieldListAutoCompleteDropdown
v-model="sort.fk_column_id"
@ -187,6 +183,7 @@ onMounted(() => {
v-if="availableColumns.length"
v-model:visible="showCreateSort"
:trigger="['click']"
class="mt-3"
overlay-class-name="nc-toolbar-dropdown"
>
<template v-if="isEeUI && !isPublic">
@ -204,6 +201,7 @@ onMounted(() => {
{{ $t('activity.addSort') }}
</div>
</NcButton>
<span v-else></span>
</template>
<template v-else>
<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>
<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">
<VirtualCellComponentsItemChip
:item="value"

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

@ -2,24 +2,13 @@
import { handleTZ } from 'nocodb-sdk'
import type { ColumnType } from 'nocodb-sdk'
import type { Ref } from 'vue'
import {
CellValueInj,
ColumnInj,
IsExpandedFormOpenInj,
computed,
inject,
renderValue,
replaceUrlsWithLink,
useBase,
} from '#imports'
import { CellValueInj, ColumnInj, computed, inject, renderValue, replaceUrlsWithLink, useBase } from '#imports'
// todo: column type doesn't have required property `error` - throws in typecheck
const column = inject(ColumnInj) as Ref<ColumnType & { colOptions: { error: any } }>
const cellValue = inject(CellValueInj)
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const { isPg } = useBase()
const result = computed(() =>
@ -40,15 +29,8 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning, activ
</template>
<span>ERR!</span>
</a-tooltip>
<span v-else-if="cellValue === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span>
<div
v-else
class="py-1"
:class="{
'px-2': isExpandedFormOpen,
}"
@dblclick="activateShowEditNonEditableFieldWarning"
>
<div v-else class="nc-cell-field py-1" @dblclick="activateShowEditNonEditableFieldWarning">
<div v-if="urls" v-html="urls" />
<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 { ref } from 'vue'
import type { Ref } from 'vue'
import {
ActiveCellInj,
CellValueInj,
ColumnInj,
IsExpandedFormOpenInj,
IsUnderLookupInj,
inject,
useSelectedCellKeyupListener,
} from '#imports'
import { ActiveCellInj, CellValueInj, ColumnInj, IsUnderLookupInj, inject, useSelectedCellKeyupListener } from '#imports'
const value = inject(CellValueInj, ref(0))
@ -27,8 +19,6 @@ const readOnly = inject(ReadonlyInj, ref(false))
const isUnderLookup = inject(IsUnderLookupInj, ref(false))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const colTitle = computed(() => column.value?.title || '')
const listItemsDlg = ref(false)
@ -130,13 +120,7 @@ watch([listItemsDlg], () => {
</script>
<template>
<div
class="flex w-full group items-center nc-links-wrapper py-1"
:class="{
'px-2': isExpandedFormOpen,
}"
@dblclick.stop="openChildList"
>
<div class="nc-cell-field flex w-full group items-center nc-links-wrapper py-1" @dblclick.stop="openChildList">
<div class="block flex-shrink truncate">
<component
:is="isUnderLookup ? 'span' : 'a'"
@ -145,7 +129,7 @@ watch([listItemsDlg], () => {
:title="textVal"
class="text-center nc-datatype-link underline-transparent"
:class="{ '!text-gray-300': !textVal }"
tabindex="0"
:tabindex="readOnly ? -1 : 0"
@click.stop.prevent="openChildList"
@keydown.enter.stop.prevent="openChildList"
>
@ -157,7 +141,7 @@ watch([listItemsDlg], () => {
<div
v-if="!isUnderLookup"
ref="plusBtnRef"
tabindex="0"
:tabindex="readOnly ? -1 : 0"
class="!xs:hidden flex group justify-end group-hover:flex items-center"
@keydown.enter.stop="openListDlg"
>

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

@ -100,7 +100,7 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning, activ
<template>
<div
class="h-full w-full nc-lookup-cell"
class="nc-cell-field h-full w-full nc-lookup-cell"
tabindex="-1"
:style="{ height: isGroupByLabel ? undefined : rowHeight && rowHeight !== 1 ? `${rowHeight * 2}rem` : `2.85rem` }"
@dblclick="activateShowEditNonEditableFieldWarning"
@ -185,7 +185,7 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning, activ
:read-only="true"
:class="{
'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>

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

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

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

@ -90,13 +90,13 @@ const rowHeight = inject(RowHeightInj, ref(undefined))
</JsBarcodeWrapper>
</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') }}
</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') }}
</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') }}
</div>
</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 readonly = inject(ReadonlyInj, ref(false))
const readOnly = inject(ReadonlyInj, ref(false))
const { isSharedBase } = storeToRefs(useBase())
@ -107,7 +107,7 @@ const expandedFormRow = ref({})
const colTitle = computed(() => injectedColumn.value?.title || '')
const onClick = (row: Row) => {
if (readonly.value) return
if (readOnly.value) return
expandedFormRow.value = row
expandedFormDlg.value = true
}
@ -166,7 +166,7 @@ const isDataExist = computed<boolean>(() => {
const linkOrUnLink = (rowRef: Record<string, string>, id: string) => {
if (isSharedBase.value) return
if (readonly.value) return
if (readOnly.value) return
if (isPublic.value && !isForm.value) return
if (isNew.value || isChildrenListLinked.value[parseInt(id)]) {
@ -276,7 +276,7 @@ const linkOrUnLink = (rowRef: Record<string, string>, id: string) => {
{{ relatedTableMeta?.title }}
</p>
<NcButton
v-if="!readonly && childrenListCount < 1"
v-if="!readOnly && childrenListCount < 1"
v-e="['c:links:link']"
data-testid="nc-child-list-button-link-to"
@click="emit('attachRecord')"
@ -322,7 +322,7 @@ const linkOrUnLink = (rowRef: Record<string, string>, id: string) => {
<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="!readonly && childrenListCount > 0"
v-if="!readOnly && childrenListCount > 0"
v-e="['c:links:link']"
data-testid="nc-child-list-button-link-to"
@click="emit('attachRecord')"

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

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

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

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

Loading…
Cancel
Save