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"> |
<script lang="ts" setup> |
||||||
import { useVModel } from '#imports' |
import type { VNodeRef } from '@vue/runtime-core' |
||||||
|
import isMobilePhone from 'validator/lib/isMobilePhone' |
||||||
|
import { EditColumnInj, EditModeInj, IsExpandedFormOpenInj, IsSurveyFormInj, computed, inject } from '#imports' |
||||||
|
|
||||||
interface Props { |
interface Props { |
||||||
modelValue: any |
modelValue: string | null | number | undefined |
||||||
} |
} |
||||||
|
|
||||||
interface Emits { |
const { modelValue: value } = defineProps<Props>() |
||||||
(event: 'update:modelValue', model: string): void |
|
||||||
} |
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> |
</script> |
||||||
|
|
||||||
<template> |
<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> |
</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