Browse Source

feat: simplified default value

pull/6323/head
DarkPhoenix2704 10 months ago
parent
commit
2e3611deb7
  1. 4
      packages/nc-gui/assets/style.scss
  2. 4
      packages/nc-gui/components/cell/Checkbox.vue
  3. 5
      packages/nc-gui/components/cell/Currency.vue
  4. 2
      packages/nc-gui/components/cell/DateTimePicker.vue
  5. 5
      packages/nc-gui/components/cell/Decimal.vue
  6. 9
      packages/nc-gui/components/cell/Duration.vue
  7. 7
      packages/nc-gui/components/cell/Email.vue
  8. 3
      packages/nc-gui/components/cell/Float.vue
  9. 5
      packages/nc-gui/components/cell/Integer.vue
  10. 5
      packages/nc-gui/components/cell/Percent.vue
  11. 80
      packages/nc-gui/components/cell/PhoneNumber.vue
  12. 8
      packages/nc-gui/components/cell/Text.vue
  13. 5
      packages/nc-gui/components/cell/TextArea.vue
  14. 7
      packages/nc-gui/components/cell/Url.vue
  15. 56
      packages/nc-gui/components/smartsheet/Cell.vue
  16. 22
      packages/nc-gui/components/smartsheet/column/AdvancedOptions.vue
  17. 31
      packages/nc-gui/components/smartsheet/column/DefaultValue.vue
  18. 51
      packages/nc-gui/components/smartsheet/column/EditOrAdd.vue
  19. 10
      packages/nc-gui/components/smartsheet/column/SelectOptions.vue
  20. 1
      packages/nc-gui/composables/useData.ts
  21. 2
      packages/nc-gui/utils/validation.ts
  22. 5
      packages/nocodb-sdk/src/lib/sqlUi/SqliteUi.ts
  23. 6
      packages/nocodb/src/db/sql-client/lib/pg/PgClient.ts
  24. 26
      packages/nocodb/src/schema/swagger.json

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

@ -534,3 +534,7 @@ a {
.nc-toolbar-dropdown {
@apply !rounded-2xl;
}
input[type='number'] {
@apply !outline-none !ring-0 !border-0;
}

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

@ -47,7 +47,7 @@ const checkboxMeta = computed(() => {
})
const vModel = computed<boolean | number>({
get: () => !!props.modelValue && props.modelValue !== '0' && props.modelValue !== 0,
get: () => !!props.modelValue && props.modelValue !== '0' && props.modelValue !== 0 && props.modelValue !== 'false',
set: (val: any) => emits('update:modelValue', isMssql(column?.value?.base_id) ? +val : val),
})
@ -75,7 +75,7 @@ useSelectedCellKeyupListener(active, (e) => {
<template>
<div
class="flex cursor-pointer w-full h-full"
class="flex cursor-pointer w-full h-full py-1"
:class="{
'justify-center': !isForm,
'w-full': isForm,

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

@ -4,6 +4,7 @@ import { ColumnInj, EditModeInj, IsExpandedFormOpenInj, computed, inject, parseP
interface Props {
modelValue: number | null | undefined
isFocus?: boolean
}
const props = defineProps<Props>()
@ -55,7 +56,7 @@ const currency = computed(() => {
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && (el as HTMLInputElement)?.focus()
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && props.isFocus && (el as HTMLInputElement)?.focus()
const submitCurrency = () => {
if (lastSaved.value !== vModel.value) {
@ -76,7 +77,7 @@ onMounted(() => {
:ref="focus"
v-model="vModel"
type="number"
class="w-full h-full border-none outline-none px-2"
class="w-full h-full border-none rounded-md outline-none"
@blur="submitCurrency"
@keydown.down.stop
@keydown.left.stop

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

@ -249,7 +249,7 @@ const isColDisabled = computed(() => {
:disabled="isColDisabled"
:show-time="true"
:bordered="false"
class="!w-full !px-0 !border-none"
class="!w-full !px-0 !py-1 !border-none"
:class="{ 'nc-null': modelValue === null && showNull }"
:format="dateTimeFormat"
:placeholder="placeholder"

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

@ -7,6 +7,7 @@ interface Props {
// for sqlite, when we clear a cell or empty the cell, it returns ""
// otherwise, it is null type
modelValue?: number | null | string
isFocus?: boolean
}
interface Emits {
@ -78,7 +79,7 @@ const onKeyDown = (e: any) => {
}
}
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && (el as HTMLInputElement)?.focus()
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && props.isFocus && (el as HTMLInputElement)?.focus()
watch(isExpandedFormOpen, () => {
if (!isExpandedFormOpen.value) {
@ -92,7 +93,7 @@ watch(isExpandedFormOpen, () => {
v-if="editEnabled"
:ref="focus"
v-model="vModel"
class="outline-none !p-0 border-none w-full h-full text-sm"
class="outline-none !py-2 !px-0 border-none rounded-md w-full h-full text-sm"
type="number"
:step="precision"
style="letter-spacing: 0.06rem"

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

@ -16,9 +16,10 @@ import {
interface Props {
modelValue: number | string | null | undefined
showValidationError?: boolean
isFocus?: boolean
}
const { modelValue, showValidationError = true } = defineProps<Props>()
const { modelValue, showValidationError = true, isFocus } = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
@ -76,7 +77,7 @@ const submitDuration = () => {
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && (el as HTMLInputElement)?.focus()
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && isFocus && (el as HTMLInputElement)?.focus()
</script>
<template>
@ -85,8 +86,8 @@ const focus: VNodeRef = (el) => !isExpandedFormOpen.value && (el as HTMLInputEle
v-if="editEnabled"
:ref="focus"
v-model="localState"
class="w-full !border-none p-0"
:class="{ '!px-2': editEnabled }"
class="w-full !border-none !outline-none p-0"
:class="{ '!px-2 !py-1': editEnabled }"
:placeholder="durationPlaceholder"
@blur="submitDuration"
@keypress="checkDurationFormat($event)"

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

@ -4,9 +4,10 @@ import { EditModeInj, IsExpandedFormOpenInj, IsSurveyFormInj, computed, inject,
interface Props {
modelValue: string | null | undefined
isFocus?: boolean
}
const { modelValue: value } = defineProps<Props>()
const { modelValue: value, isFocus } = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
@ -39,7 +40,7 @@ const validEmail = computed(() => vModel.value && validateEmail(vModel.value))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && (el as HTMLInputElement)?.focus()
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && isFocus && (el as HTMLInputElement)?.focus()
watch(
() => editEnabled.value,
@ -59,7 +60,7 @@ watch(
v-if="editEnabled"
:ref="focus"
v-model="vModel"
class="w-full outline-none text-sm px-2"
class="w-full outline-none text-sm py-2"
@blur="editEnabled = false"
@keydown.down.stop
@keydown.left.stop

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

@ -7,6 +7,7 @@ interface Props {
// for sqlite, when we clear a cell or empty the cell, it returns ""
// otherwise, it is null type
modelValue?: number | null | string
isFocus?: boolean
}
interface Emits {
@ -38,7 +39,7 @@ const vModel = computed({
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && (el as HTMLInputElement)?.focus()
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && props.isFocus && (el as HTMLInputElement)?.focus()
</script>
<template>

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

@ -7,6 +7,7 @@ interface Props {
// for sqlite, when we clear a cell or empty the cell, it returns ""
// otherwise, it is null type
modelValue?: number | null | string
isFocus?: boolean
}
interface Emits {
@ -46,7 +47,7 @@ const vModel = computed({
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && (el as HTMLInputElement)?.focus()
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && props.isFocus && (el as HTMLInputElement)?.focus()
function onKeyDown(e: any) {
const cmdOrCtrl = isMac() ? e.metaKey : e.ctrlKey
@ -83,7 +84,7 @@ function onKeyDown(e: any) {
v-if="editEnabled"
:ref="focus"
v-model="vModel"
class="outline-none p-0 border-none w-full h-full text-sm"
class="outline-none !py-2 px-0 border-none w-full h-full text-sm"
type="number"
style="letter-spacing: 0.06rem"
@blur="editEnabled = false"

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

@ -4,6 +4,7 @@ import { EditModeInj, IsExpandedFormOpenInj, inject, useVModel } from '#imports'
interface Props {
modelValue?: number | string | null
isFocus?: boolean
}
const props = defineProps<Props>()
@ -29,7 +30,7 @@ const vModel = computed({
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && (el as HTMLInputElement)?.focus()
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && props.isFocus && (el as HTMLInputElement)?.focus()
</script>
<template>
@ -37,7 +38,7 @@ const focus: VNodeRef = (el) => !isExpandedFormOpen.value && (el as HTMLInputEle
v-if="editEnabled"
:ref="focus"
v-model="vModel"
class="w-full !border-none text-base"
class="w-full !border-none !outline-none focus:ring-0 text-base py-1"
:class="{ '!px-2': editEnabled }"
type="number"
@blur="editEnabled = false"

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

@ -1,21 +1,81 @@
<script setup lang="ts">
import { useVModel } from '#imports'
<script lang="ts" setup>
import type { VNodeRef } from '@vue/runtime-core'
import { EditModeInj, IsExpandedFormOpenInj, IsSurveyFormInj, computed, inject, validatePhone } from '#imports'
interface Props {
modelValue: any
modelValue: string | null | number | undefined
isFocus?: boolean
}
interface Emits {
(event: 'update:modelValue', model: string): void
}
const { modelValue: value, isFocus } = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
const rowHeight = inject(RowHeightInj, ref(undefined))
const { showNull } = useGlobal()
const editEnabled = inject(EditModeInj)!
const column = inject(ColumnInj)!
// 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 props = defineProps<Props>()
const isSurveyForm = inject(IsSurveyFormInj, ref(false))
const emits = defineEmits<Emits>()
const vModel = computed({
get: () => value,
set: (val) => {
localState.value = val
if (!parseProp(column.value.meta)?.validate || (val && validatePhone(val)) || !val || isSurveyForm.value) {
emit('update:modelValue', val)
}
},
})
const vModel = useVModel(props, 'modelValue', emits)
const validEmail = computed(() => vModel.value && validatePhone(vModel.value))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && isFocus && (el as HTMLInputElement)?.focus()
watch(
() => editEnabled.value,
() => {
if (parseProp(column.value.meta)?.validate && !editEnabled.value && localState.value && !validatePhone(localState.value)) {
message.error('Invalid Phone Number')
localState.value = undefined
return
}
localState.value = value
},
)
</script>
<template>
<LazyCellText v-model="vModel" />
<input
v-if="editEnabled"
:ref="focus"
v-model="vModel"
class="w-full outline-none text-sm py-2"
@blur="editEnabled = false"
@keydown.down.stop
@keydown.left.stop
@keydown.right.stop
@keydown.up.stop
@keydown.delete.stop
@keydown.ctrl.z.stop
@keydown.meta.z.stop
@selectstart.capture.stop
@mousedown.stop
/>
<span v-else-if="vModel === null && showNull" class="nc-null">NULL</span>
<a v-else-if="validEmail" class="text-sm underline hover:opacity-75" :href="`tel:${vModel}`" target="_blank">
<LazyCellClampedText :value="vModel" :lines="rowHeight" />
</a>
<LazyCellClampedText v-else :value="vModel" :lines="rowHeight" />
</template>

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

@ -4,6 +4,7 @@ import { EditModeInj, IsExpandedFormOpenInj, ReadonlyInj, RowHeightInj, inject,
interface Props {
modelValue?: string | null
isFocus?: boolean
}
const props = defineProps<Props>()
@ -12,7 +13,7 @@ const emits = defineEmits(['update:modelValue'])
const { showNull } = useGlobal()
const editEnabled = inject(EditModeInj)
const editEnabled = inject(EditModeInj, ref(false))
const rowHeight = inject(RowHeightInj, ref(undefined))
@ -22,7 +23,7 @@ const vModel = useVModel(props, 'modelValue', emits)
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && (el as HTMLInputElement)?.focus()
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && props.isFocus && (el as HTMLInputElement)?.focus()
</script>
<template>
@ -30,8 +31,7 @@ const focus: VNodeRef = (el) => !isExpandedFormOpen.value && (el as HTMLInputEle
v-if="!readonly && editEnabled"
:ref="focus"
v-model="vModel"
class="h-full w-full outline-none bg-transparent"
:class="{ '!px-2': editEnabled }"
class="h-full w-full outline-none p-2 bg-transparent"
@blur="editEnabled = false"
@keydown.down.stop
@keydown.left.stop

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

@ -4,13 +4,14 @@ import { ActiveCellInj, EditModeInj, IsExpandedFormOpenInj, RowHeightInj, iconMa
const props = defineProps<{
modelValue?: string | number
isFocus?: boolean
}>()
const emits = defineEmits(['update:modelValue'])
const column = inject(ColumnInj)
const editEnabled = inject(EditModeInj)
const editEnabled = inject(EditModeInj, ref(false))
const rowHeight = inject(RowHeightInj, ref(undefined))
@ -20,7 +21,7 @@ const vModel = useVModel(props, 'modelValue', emits, { defaultValue: '' })
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && (el as HTMLTextAreaElement)?.focus()
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && props.isFocus && (el as HTMLTextAreaElement)?.focus()
const height = computed(() => {
if (!rowHeight.value) return 60

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

@ -19,9 +19,10 @@ import {
interface Props {
modelValue?: string | null
isFocus?: boolean
}
const { modelValue: value } = defineProps<Props>()
const { modelValue: value, isFocus } = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
@ -67,7 +68,7 @@ const { cellUrlOptions } = useCellUrlConfig(url)
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && (el as HTMLInputElement)?.focus()
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && isFocus && (el as HTMLInputElement)?.focus()
watch(
() => editEnabled.value,
@ -88,7 +89,7 @@ watch(
v-if="editEnabled"
:ref="focus"
v-model="vModel"
class="outline-none text-sm w-full px-2 bg-transparent h-full"
class="outline-none text-sm w-full px-2 py-2 bg-transparent h-full"
@blur="editEnabled = false"
@keydown.down.stop
@keydown.left.stop

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

@ -1,6 +1,6 @@
<script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk'
import { isSystemColumn } from 'nocodb-sdk'
import { UITypes, isSystemColumn } from 'nocodb-sdk'
import {
ActiveCellInj,
ColumnInj,
@ -61,7 +61,7 @@ interface Props {
const props = defineProps<Props>()
const emit = defineEmits(['update:modelValue', 'save', 'navigate', 'update:editEnabled'])
const emit = defineEmits(['update:modelValue', 'save', 'navigate', 'update:editEnabled', 'update:value'])
const column = toRef(props, 'column')
@ -87,6 +87,8 @@ const isLocked = inject(IsLockedInj, ref(false))
const isSurveyForm = inject(IsSurveyFormInj, ref(false))
const isAdvancedOption = inject('isAdvancedOption', ref(false))
const { currentRow } = useSmartsheetRowStoreOrThrow()
const { sqlUis } = storeToRefs(useProject())
@ -109,7 +111,10 @@ const vModel = computed({
return props.modelValue
},
set: (val) => {
if (val !== props.modelValue) {
if (isAdvancedOption.value) {
column.value.cdf = val
emit('update:value', val)
} else if (val !== props.modelValue) {
currentRow.value.rowMeta.changed = true
emit('update:modelValue', val)
if (isAutoSaved(column.value)) {
@ -173,6 +178,9 @@ function initIntersectionObserver() {
})
}
const numberInputAlignment = computed(() => {
return isAdvancedOption.value ? 'left' : 'right'
})
// observe the cell when it is mounted
onMounted(() => {
initIntersectionObserver()
@ -201,12 +209,22 @@ onUnmounted(() => {
>
<template v-if="column">
<template v-if="intersected">
<LazyCellTextArea v-if="isTextArea(column)" v-model="vModel" />
<LazyCellTextArea v-if="isTextArea(column)" v-model="vModel" :is-focus="!isAdvancedOption" />
<LazyCellGeoData v-else-if="isGeoData(column)" v-model="vModel" />
<LazyCellCheckbox v-else-if="isBoolean(column, abstractType)" v-model="vModel" />
<LazyCellAttachment v-else-if="isAttachment(column)" v-model="vModel" :row-index="props.rowIndex" />
<LazyCellSingleSelect v-else-if="isSingleSelect(column)" v-model="vModel" :row-index="props.rowIndex" />
<LazyCellMultiSelect v-else-if="isMultiSelect(column)" v-model="vModel" :row-index="props.rowIndex" />
<LazyCellSingleSelect
v-else-if="isSingleSelect(column)"
v-model="vModel"
:disable-option-creation="!!isAdvancedOption"
:row-index="props.rowIndex"
/>
<LazyCellMultiSelect
v-else-if="isMultiSelect(column)"
v-model="vModel"
:disable-option-creation="!!isAdvancedOption"
:row-index="props.rowIndex"
/>
<LazyCellDatePicker v-else-if="isDate(column, abstractType)" v-model="vModel" :is-pk="isPrimaryKey(column)" />
<LazyCellYearPicker v-else-if="isYear(column, abstractType)" v-model="vModel" :is-pk="isPrimaryKey(column)" />
<LazyCellDateTimePicker
@ -217,18 +235,18 @@ onUnmounted(() => {
/>
<LazyCellTimePicker v-else-if="isTime(column, abstractType)" v-model="vModel" :is-pk="isPrimaryKey(column)" />
<LazyCellRating v-else-if="isRating(column)" v-model="vModel" />
<LazyCellDuration v-else-if="isDuration(column)" v-model="vModel" />
<LazyCellEmail v-else-if="isEmail(column)" v-model="vModel" />
<LazyCellUrl v-else-if="isURL(column)" v-model="vModel" />
<LazyCellPhoneNumber v-else-if="isPhoneNumber(column)" v-model="vModel" />
<LazyCellPercent v-else-if="isPercent(column)" v-model="vModel" />
<LazyCellCurrency v-else-if="isCurrency(column)" v-model="vModel" @save="emit('save')" />
<LazyCellDecimal v-else-if="isDecimal(column)" v-model="vModel" />
<LazyCellInteger v-else-if="isInt(column, abstractType)" v-model="vModel" />
<LazyCellFloat v-else-if="isFloat(column, abstractType)" v-model="vModel" />
<LazyCellText v-else-if="isString(column, abstractType)" v-model="vModel" />
<LazyCellDuration v-else-if="isDuration(column)" v-model="vModel" :is-focus="!isAdvancedOption" />
<LazyCellEmail v-else-if="isEmail(column)" v-model="vModel" :is-focus="!isAdvancedOption" />
<LazyCellUrl v-else-if="isURL(column)" v-model="vModel" :is-focus="!isAdvancedOption" />
<LazyCellPhoneNumber v-else-if="isPhoneNumber(column)" v-model="vModel" :is-focus="!isAdvancedOption" />
<LazyCellPercent v-else-if="isPercent(column)" v-model="vModel" :is-focus="!isAdvancedOption" />
<LazyCellCurrency v-else-if="isCurrency(column)" v-model="vModel" :is-focus="!isAdvancedOption" @save="emit('save')" />
<LazyCellDecimal v-else-if="isDecimal(column)" v-model="vModel" :is-focus="!isAdvancedOption" />
<LazyCellInteger v-else-if="isInt(column, abstractType)" v-model="vModel" :is-focus="!isAdvancedOption" />
<LazyCellFloat v-else-if="isFloat(column, abstractType)" v-model="vModel" :is-focus="!isAdvancedOption" />
<LazyCellText v-else-if="isString(column, abstractType)" v-model="vModel" :is-focus="!isAdvancedOption" />
<LazyCellJson v-else-if="isJSON(column)" v-model="vModel" />
<LazyCellText v-else v-model="vModel" />
<LazyCellText v-else v-model="vModel" :is-focus="!isAdvancedOption" />
<div
v-if="(isLocked || (isPublic && readOnly && !isForm) || isSystemColumn(column)) && !isAttachment(column)"
class="nc-locked-overlay"
@ -240,9 +258,9 @@ onUnmounted(() => {
<style scoped lang="scss">
.nc-grid-numeric-cell {
@apply text-right;
text-align: v-bind(numberInputAlignment);
:deep(input) {
@apply text-right;
text-align: v-bind(numberInputAlignment);
}
}
</style>

22
packages/nc-gui/components/smartsheet/column/AdvancedOptions.vue

@ -20,17 +20,6 @@ const { isPg } = useProject()
const meta = inject(MetaInj, ref())
const sampleValue = computed(() => {
switch (vModel.value.uidt) {
case UITypes.SingleSelect:
return 'eg : a'
case UITypes.MultiSelect:
return 'eg : a,b,c'
default:
return sqlUi.value.getDefaultValueForDatatype(vModel.value.dt)
}
})
const hideLength = computed(() => {
return [UITypes.SingleSelect, UITypes.MultiSelect].includes(vModel.value.uidt)
})
@ -44,7 +33,7 @@ vModel.value.au = !!vModel.value.au */
</script>
<template>
<div class="p-4 border-[0.1px] radius-1 border-grey w-full flex flex-col gap-2">
<div class="p-4 border-[0.1px] radius-1 rounded-md border-grey w-full flex flex-col gap-2">
<template v-if="props.advancedDbOptions">
<div class="flex justify-between w-full gap-1">
<a-form-item label="NN">
@ -91,8 +80,6 @@ vModel.value.au = !!vModel.value.au */
</a-select>
</a-form-item>
<LazySmartsheetColumnPgBinaryOptions v-if="isPg(meta.base_id) && vModel.dt === 'bytea'" v-model:value="vModel" />
<a-form-item v-if="!hideLength" :label="$t('labels.lengthValue')">
<a-input
v-model:value="vModel.dtxp"
@ -104,11 +91,8 @@ vModel.value.au = !!vModel.value.au */
<a-form-item v-if="sqlUi.showScale(vModel)" label="Scale">
<a-input v-model:value="vModel.dtxs" :disabled="!sqlUi.columnEditable(vModel)" @input="onAlter" />
</a-form-item>
</template>
<a-form-item :label="$t('placeholder.defaultValue')">
<a-textarea v-model:value="vModel.cdf" auto-size @input="onAlter(2, true)" />
<span class="text-gray-400 text-xs">{{ sampleValue }}</span>
</a-form-item>
<LazySmartsheetColumnPgBinaryOptions v-if="isPg(meta?.base_id) && vModel.dt === 'bytea'" v-model:value="vModel" />
</template>
</div>
</template>

31
packages/nc-gui/components/smartsheet/column/DefaultValue.vue

@ -0,0 +1,31 @@
<script lang="ts" setup>
const props = defineProps<{
value: any
}>()
const emit = defineEmits(['update:value'])
const column = inject(ColumnInj)
provide('isAdvancedOption', ref(true))
const rowRef = ref({
row: {},
oldRow: {},
rowMeta: {
isUpdatedFromCopyNPaste: [column?.value.title],
},
})
const vModel = useVModel(props, 'value', emit)
useProvideSmartsheetRowStore(vModel, rowRef)
</script>
<template>
<p class="mt-3 text-[0.75rem]">Default Value</p>
<div class="border-1 px-1 my-[-4px] border-gray-300 rounded-md">
<LazySmartsheetCell :column="vModel" :model-value="vModel.cdf" :edit-enabled="true" />
</div>
</template>
<style scoped></style>

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

@ -8,7 +8,8 @@ import {
ReloadViewDataHookInj,
computed,
inject,
isEeUI,
isJSON,
isTextArea,
message,
onMounted,
ref,
@ -18,6 +19,7 @@ import {
useI18n,
useMetas,
useNuxtApp,
useProject,
watchEffect,
} from '#imports'
import MdiPlusIcon from '~icons/mdi/plus-circle-outline'
@ -63,12 +65,12 @@ const isForm = inject(IsFormInj, ref(false))
const isKanban = inject(IsKanbanInj, ref(false))
const { isMysql, isMssql } = useProject()
const reloadDataTrigger = inject(ReloadViewDataHookInj)
const advancedOptions = ref(false)
const advancedDbOptions = ref(false)
const mounted = ref(false)
const columnToValidate = [UITypes.Email, UITypes.URL, UITypes.PhoneNumber]
@ -262,7 +264,7 @@ if (props.fromTableExplorer) {
</a-select-option>
</a-select>
</a-form-item>
<div v-if="isEeUI && !props.hideType" class="mt-2 cursor-pointer" @click="predictColumnType()">
<div v-if="!props.hideType" class="mt-2 cursor-pointer" @click="predictColumnType()">
<GeneralIcon icon="magic" :class="{ 'nc-animation-pulse': loadMagic }" class="w-full flex mt-2 text-orange-400" />
</div>
</div>
@ -290,12 +292,32 @@ if (props.fromTableExplorer) {
v-model:value="formState"
/>
</div>
<a-checkbox
v-if="formState.meta && columnToValidate.includes(formState.uidt)"
v-model:checked="formState.meta.validate"
class="ml-1 mb-1"
>
<span class="text-[10px] text-gray-600">
{{ `Accept only valid ${formState.uidt}` }}
</span>
</a-checkbox>
<!--
Default Value for JSON & LongText is not supported in MySQL
Default Value is Disabled for MSSQL -->
<LazySmartsheetColumnDefaultValue
v-if="
!isVirtualCol(formState) &&
!isAttachment(formState) &&
!isMssql(meta!.base_id) &&
!(isMysql(meta!.base_id) && (isJSON(formState) || isTextArea(formState)))
"
v-model:value="formState"
/>
<div
v-if="!props.hideAdditionalOptions && !isVirtualCol(formState.uidt)"
v-if="!props.hideAdditionalOptions && !isVirtualCol(formState.uidt) && !appInfo.ee"
class="text-xs cursor-pointer text-gray-400 nc-more-options mb-1 mt-4 flex items-center gap-1 justify-end"
@click="advancedOptions = !advancedOptions"
@dblclick="advancedDbOptions = !advancedDbOptions"
>
{{ advancedOptions ? $t('general.hideAll') : $t('general.showMore') }}
<component :is="advancedOptions ? MdiMinusIcon : MdiPlusIcon" />
@ -303,25 +325,12 @@ if (props.fromTableExplorer) {
<Transition name="layout" mode="out-in">
<div v-if="advancedOptions" class="overflow-hidden">
<a-checkbox
v-if="formState.meta && columnToValidate.includes(formState.uidt)"
v-model:checked="formState.meta.validate"
class="ml-1 mb-1"
>
<span class="text-[10px] text-gray-600">
{{ `Accept only valid ${formState.uidt}` }}
</span>
</a-checkbox>
<LazySmartsheetColumnAttachmentOptions
v-if="appInfo.ee && formState.uidt === UITypes.Attachment"
v-model:value="formState"
/>
<LazySmartsheetColumnAttachmentOptions v-if="appInfo.ee && isAttachment(formState)" v-model:value="formState" />
<LazySmartsheetColumnAdvancedOptions
v-if="formState.uidt !== UITypes.Attachment"
v-model:value="formState"
:advanced-db-options="advancedDbOptions || formState.uidt === UITypes.SpecificDBType"
:advanced-db-options="advancedOptions || formState.uidt === UITypes.SpecificDBType"
/>
</div>
</Transition>

10
packages/nc-gui/components/smartsheet/column/SelectOptions.vue

@ -184,6 +184,16 @@ watch(inputs, () => {
inputs.value.$el.focus()
}
})
watch(vModel.value, (next) => {
if (vModel.value.uidt === UITypes.MultiSelect) {
const cdfs = next.cdf.split(',')
const values = next.colOptions.options.map((col) => {
return col.title
})
vModel.value.cdf = cdfs.filter((c: string) => values.includes(c)).join(',')
}
})
</script>
<template>

1
packages/nc-gui/composables/useData.ts

@ -243,6 +243,7 @@ export function useData(args: {
col.uidt === UITypes.QrCode ||
col.uidt === UITypes.Barcode ||
col.uidt === UITypes.Rollup ||
col.uidt === UITypes.Checkbox ||
col.au ||
col.cdf?.includes(' on update ')
)

2
packages/nc-gui/utils/validation.ts

@ -3,6 +3,8 @@ import { getI18n } from '../plugins/a.i18n'
export const validateEmail = (v: string) =>
/^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i.test(v)
export const validatePhone = (v: string) => /^[0-9+]{6,}$/.test(v)
export const validateTableName = {
validator: (_: unknown, value: string) => {
return new Promise((resolve, reject) => {

5
packages/nocodb-sdk/src/lib/sqlUi/SqliteUi.ts

@ -261,13 +261,12 @@ export class SqliteUi {
/^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*PROCEDURE\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
const match = query.match(reg);
return match && match[1];
}
}*/
static columnEditable(_colObj) {
return true; // colObj.altered === 1;
}
static handleRawOutput(result, headers) {
/*static handleRawOutput(result, headers) {
console.log(result);
if (Array.isArray(result) && result[0]) {
const keys = Object.keys(result[0]);

6
packages/nocodb/src/db/sql-client/lib/pg/PgClient.ts

@ -876,9 +876,9 @@ class PGClient extends KnexClient {
// todo : need to find if column is unique or not
// column['unique'] = response.rows[i]['cst'].indexOf('UNIQUE') === -1 ? false : true;
column.cdf = response.rows[i].cdf;
// ? response.rows[i].cdf.split("::")[0].replace(/'/g, "")
// : response.rows[i].cdf;
column.cdf = response.rows[i].cdf
? response.rows[i].cdf.split('::')[0].replace(/'/g, '')
: response.rows[i].cdf;
// todo : need to find column comment
column.cc = response.rows[i].cc;

26
packages/nocodb/src/schema/swagger.json

@ -16018,7 +16018,7 @@
"type": "string"
},
"cdf": {
"$ref": "#/components/schemas/StringOrNull",
"$ref": "#/components/schemas/StringOrNullOrBooleanOrNumber",
"description": "Column Default"
},
"clen": {
@ -19319,7 +19319,7 @@
"description": "Column Comment"
},
"cdf": {
"$ref": "#/components/schemas/StringOrNull",
"$ref": "#/components/schemas/StringOrNullOrBooleanOrNumber",
"description": "Column Default Value"
},
"column_name": {
@ -20855,6 +20855,28 @@
"id": "p1g7xrgdsn540"
}
},
"StringOrNullOrBooleanOrNumber": {
"description": "Model for StringOrNullOrBooleanOrNumber",
"examples": [
"string"
],
"oneOf": [
{
"maxLength": 255,
"type": "string"
},
{
"type": "null"
},
{
"type": "boolean"
},
{
"type": "number"
}
],
"title": "StringOrNullOrBooleanOrNumber Model"
},
"Table": {
"description": "Model for Table",
"examples": [

Loading…
Cancel
Save