mirror of https://github.com/nocodb/nocodb
Wing-Kam Wong
1 year ago
32 changed files with 449 additions and 133 deletions
@ -1,21 +1,84 @@
|
||||
<script setup lang="ts"> |
||||
import { useVModel } from '#imports' |
||||
<script lang="ts" setup> |
||||
import type { VNodeRef } from '@vue/runtime-core' |
||||
import isMobilePhone from 'validator/lib/isMobilePhone' |
||||
import { EditColumnInj, EditModeInj, IsExpandedFormOpenInj, IsSurveyFormInj, computed, inject } from '#imports' |
||||
|
||||
interface Props { |
||||
modelValue: any |
||||
modelValue: string | null | number | undefined |
||||
} |
||||
|
||||
interface Emits { |
||||
(event: 'update:modelValue', model: string): void |
||||
} |
||||
const { modelValue: value } = defineProps<Props>() |
||||
|
||||
const emit = defineEmits(['update:modelValue']) |
||||
|
||||
const rowHeight = inject(RowHeightInj, ref(undefined)) |
||||
|
||||
const { showNull } = useGlobal() |
||||
|
||||
const editEnabled = inject(EditModeInj)! |
||||
|
||||
const isEditColumn = inject(EditColumnInj, ref(false)) |
||||
|
||||
const column = inject(ColumnInj)! |
||||
|
||||
const props = defineProps<Props>() |
||||
// 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 emits = defineEmits<Emits>() |
||||
const isSurveyForm = inject(IsSurveyFormInj, ref(false)) |
||||
|
||||
const vModel = useVModel(props, 'modelValue', emits) |
||||
const vModel = computed({ |
||||
get: () => value, |
||||
set: (val) => { |
||||
localState.value = val |
||||
if (!parseProp(column.value.meta)?.validate || (val && isMobilePhone(val)) || !val || isSurveyForm.value) { |
||||
emit('update:modelValue', val) |
||||
} |
||||
}, |
||||
}) |
||||
|
||||
const validEmail = computed(() => vModel.value && isMobilePhone(vModel.value)) |
||||
|
||||
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))! |
||||
|
||||
const focus: VNodeRef = (el) => !isExpandedFormOpen.value && !isEditColumn.value && (el as HTMLInputElement)?.focus() |
||||
|
||||
watch( |
||||
() => editEnabled.value, |
||||
() => { |
||||
if (parseProp(column.value.meta)?.validate && !editEnabled.value && localState.value && !isMobilePhone(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 px-1 py-2" |
||||
:placeholder="isEditColumn ? '(Optional)' : ''" |
||||
@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> |
||||
|
@ -0,0 +1,63 @@
|
||||
<script lang="ts" setup> |
||||
import { UITypes } from 'nocodb-sdk' |
||||
import { iconMap } from '#imports' |
||||
|
||||
const props = defineProps<{ |
||||
value: any |
||||
}>() |
||||
const emit = defineEmits(['update:value']) |
||||
|
||||
provide(EditColumnInj, ref(true)) |
||||
|
||||
const vModel = useVModel(props, 'value', emit) |
||||
const rowRef = ref({ |
||||
row: {}, |
||||
oldRow: {}, |
||||
rowMeta: { |
||||
isUpdatedFromCopyNPaste: [vModel?.value.title], |
||||
}, |
||||
}) |
||||
|
||||
const cdfValue = computed({ |
||||
get: () => { |
||||
if (vModel.value.uidt === UITypes.MultiSelect || vModel.value.uidt === UITypes.SingleSelect) { |
||||
return (vModel.value.cdf ?? '').replaceAll("'", '') |
||||
} else if ( |
||||
vModel.value.uidt === UITypes.SingleLineText || |
||||
vModel.value.uidt === UITypes.LongText || |
||||
vModel.value.uidt === UITypes.Email || |
||||
vModel.value.uidt === UITypes.URL || |
||||
vModel.value.uidt === UITypes.JSON || |
||||
vModel.value.uidt === UITypes.DateTime || |
||||
vModel.value.uidt === UITypes.Time || |
||||
vModel.value.uidt === UITypes.Year || |
||||
vModel.value.uidt === UITypes.Date |
||||
) { |
||||
return (vModel.value.cdf ?? '').replace(/^'/, '').replace(/'$/, '') |
||||
} |
||||
return vModel.value.cdf |
||||
}, |
||||
set: (value) => { |
||||
vModel.value.cdf = value |
||||
}, |
||||
}) |
||||
|
||||
useProvideSmartsheetRowStore(vModel, rowRef) |
||||
</script> |
||||
|
||||
<template> |
||||
<div class="!my-3 text-xs">Default Value</div> |
||||
<div class="flex flex-row gap-2"> |
||||
<div class="border-1 flex items-center w-full px-1 my-[-4px] border-gray-300 rounded-md"> |
||||
<LazySmartsheetCell :column="vModel" :model-value="cdfValue" :edit-enabled="true" /> |
||||
<component |
||||
:is="iconMap.close" |
||||
v-if="vModel.uidt !== UITypes.Year" |
||||
class="w-4 h-4 cursor-pointer rounded-full !text-black-500 text-gray-500 cursor-pointer hover:bg-gray-50" |
||||
@click="cdfValue = null" |
||||
/> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<style scoped></style> |
Loading…
Reference in new issue